From 204ad535c060322c35b3798198e9c40db31916d5 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 09:53:57 +0900
Subject: [PATCH 01/32] wip

---
 src/web/app/auth/tags/form.tag                |  22 +-
 src/web/app/auth/tags/index.tag               |  54 +--
 src/web/app/common/tags/api-info.tag          |   2 +-
 src/web/app/common/tags/authorized-apps.tag   |  20 +-
 src/web/app/common/tags/core-error.tag        |   6 +-
 src/web/app/common/tags/file-type-icon.tag    |   2 +-
 src/web/app/common/tags/messaging/form.tag    |  89 +++--
 src/web/app/common/tags/messaging/index.tag   |  74 ++--
 src/web/app/common/tags/messaging/message.tag |  22 +-
 src/web/app/common/tags/messaging/room.tag    |  94 ++---
 src/web/app/common/tags/number.tag            |  12 +-
 src/web/app/common/tags/poll-editor.tag       |  22 +-
 src/web/app/common/tags/poll.tag              |  22 +-
 src/web/app/common/tags/raw.tag               |   2 +-
 src/web/app/common/tags/ripple-string.tag     |  14 +-
 src/web/app/common/tags/signin-history.tag    |  32 +-
 src/web/app/common/tags/signin.tag            |  48 +--
 src/web/app/common/tags/signup.tag            | 120 +++---
 src/web/app/common/tags/special-message.tag   |   4 +-
 src/web/app/common/tags/time.tag              |  34 +-
 src/web/app/common/tags/twitter-setting.tag   |   2 +-
 src/web/app/common/tags/uploader.tag          |  38 +-
 src/web/app/common/tags/url-preview.tag       |  24 +-
 src/web/app/common/tags/url.tag               |  20 +-
 src/web/app/desktop/tags/analog-clock.tag     |  30 +-
 .../desktop/tags/autocomplete-suggestion.tag  |  82 ++---
 .../app/desktop/tags/big-follow-button.tag    |  70 ++--
 src/web/app/desktop/tags/contextmenu.tag      |  36 +-
 src/web/app/desktop/tags/crop-window.tag      |  36 +-
 src/web/app/desktop/tags/dialog.tag           |  50 +--
 src/web/app/desktop/tags/donation.tag         |  12 +-
 .../desktop/tags/drive/base-contextmenu.tag   |  26 +-
 .../app/desktop/tags/drive/browser-window.tag |  16 +-
 src/web/app/desktop/tags/drive/browser.tag    | 342 +++++++++---------
 .../desktop/tags/drive/file-contextmenu.tag   |  62 ++--
 src/web/app/desktop/tags/drive/file.tag       |  52 +--
 .../desktop/tags/drive/folder-contextmenu.tag |  46 +--
 src/web/app/desktop/tags/drive/folder.tag     | 120 +++---
 src/web/app/desktop/tags/drive/nav-folder.tag |  84 ++---
 src/web/app/desktop/tags/follow-button.tag    |  70 ++--
 .../app/desktop/tags/following-setuper.tag    |  40 +-
 src/web/app/desktop/tags/go-top.tag           |  12 +-
 .../desktop/tags/home-widgets/calendar.tag    |  30 +-
 .../desktop/tags/home-widgets/donation.tag    |   2 +-
 .../desktop/tags/home-widgets/mentions.tag    |  82 ++---
 .../tags/home-widgets/notifications.tag       |   6 +-
 .../tags/home-widgets/photo-stream.tag        |  30 +-
 .../app/desktop/tags/home-widgets/profile.tag |  12 +-
 .../desktop/tags/home-widgets/rss-reader.tag  |  30 +-
 .../desktop/tags/home-widgets/timeline.tag    | 102 +++---
 .../app/desktop/tags/home-widgets/tips.tag    |  24 +-
 .../tags/home-widgets/user-recommendation.tag |  40 +-
 src/web/app/desktop/tags/home.tag             |  30 +-
 src/web/app/desktop/tags/image-dialog.tag     |  36 +-
 src/web/app/desktop/tags/images-viewer.tag    |  18 +-
 src/web/app/desktop/tags/input-dialog.tag     |  44 +--
 src/web/app/desktop/tags/list-user.tag        |   2 +-
 .../desktop/tags/messaging/room-window.tag    |   8 +-
 src/web/app/desktop/tags/messaging/window.tag |  10 +-
 src/web/app/desktop/tags/notifications.tag    |  38 +-
 src/web/app/desktop/tags/pages/entrance.tag   |  20 +-
 .../desktop/tags/pages/entrance/signin.tag    |   8 +-
 src/web/app/desktop/tags/pages/home.tag       |  44 +--
 src/web/app/desktop/tags/pages/post.tag       |  16 +-
 src/web/app/desktop/tags/pages/search.tag     |  10 +-
 src/web/app/desktop/tags/pages/user.tag       |  16 +-
 src/web/app/desktop/tags/post-detail-sub.tag  |  36 +-
 src/web/app/desktop/tags/post-detail.tag      | 124 +++----
 src/web/app/desktop/tags/post-form-window.tag |  28 +-
 src/web/app/desktop/tags/post-form.tag        | 164 ++++-----
 src/web/app/desktop/tags/post-preview.tag     |   8 +-
 .../app/desktop/tags/post-status-graph.tag    |  58 +--
 src/web/app/desktop/tags/progress-dialog.tag  |  24 +-
 .../app/desktop/tags/repost-form-window.tag   |  28 +-
 src/web/app/desktop/tags/repost-form.tag      |  38 +-
 src/web/app/desktop/tags/search-posts.tag     |  72 ++--
 src/web/app/desktop/tags/search.tag           |   8 +-
 .../tags/select-file-from-drive-window.tag    |  36 +-
 .../desktop/tags/set-avatar-suggestion.tag    |  10 +-
 .../desktop/tags/set-banner-suggestion.tag    |  10 +-
 src/web/app/desktop/tags/settings-window.tag  |  10 +-
 src/web/app/desktop/tags/settings.tag         |  46 +--
 src/web/app/desktop/tags/stream-indicator.tag |  30 +-
 src/web/app/desktop/tags/sub-post-content.tag |  14 +-
 .../app/desktop/tags/timeline-post-sub.tag    |   8 +-
 src/web/app/desktop/tags/timeline-post.tag    |  86 ++---
 src/web/app/desktop/tags/timeline.tag         |  34 +-
 .../app/desktop/tags/ui-header-account.tag    |  42 +--
 src/web/app/desktop/tags/ui-header-clock.tag  |  14 +-
 src/web/app/desktop/tags/ui-header-nav.tag    |  46 +--
 .../desktop/tags/ui-header-notifications.tag  |  28 +-
 .../desktop/tags/ui-header-post-button.tag    |   4 +-
 src/web/app/desktop/tags/ui-header-search.tag |   6 +-
 src/web/app/desktop/tags/ui-header.tag        |   2 +-
 src/web/app/desktop/tags/ui-notification.tag  |  20 +-
 src/web/app/desktop/tags/ui.tag               |  24 +-
 .../desktop/tags/user-followers-window.tag    |   2 +-
 src/web/app/desktop/tags/user-followers.tag   |   8 +-
 .../desktop/tags/user-following-window.tag    |   2 +-
 src/web/app/desktop/tags/user-following.tag   |   8 +-
 .../app/desktop/tags/user-friends-graph.tag   |  44 +--
 src/web/app/desktop/tags/user-graphs.tag      |   4 +-
 src/web/app/desktop/tags/user-header.tag      |  36 +-
 src/web/app/desktop/tags/user-home.tag        |   8 +-
 src/web/app/desktop/tags/user-likes-graph.tag |  30 +-
 src/web/app/desktop/tags/user-photos.tag      |  32 +-
 src/web/app/desktop/tags/user-posts-graph.tag |  48 +--
 src/web/app/desktop/tags/user-preview.tag     |  48 +--
 src/web/app/desktop/tags/user-profile.tag     |  14 +-
 src/web/app/desktop/tags/user-timeline.tag    | 114 +++---
 src/web/app/desktop/tags/user.tag             |  24 +-
 src/web/app/desktop/tags/users-list.tag       |  54 +--
 src/web/app/desktop/tags/window.tag           | 286 +++++++--------
 src/web/app/dev/tags/new-app-form.tag         |  64 ++--
 src/web/app/dev/tags/pages/app.tag            |  18 +-
 src/web/app/dev/tags/pages/apps.tag           |  16 +-
 src/web/app/mobile/tags/drive-selector.tag    |  22 +-
 src/web/app/mobile/tags/drive.tag             | 220 +++++------
 src/web/app/mobile/tags/drive/file-viewer.tag |  18 +-
 src/web/app/mobile/tags/drive/file.tag        |  14 +-
 src/web/app/mobile/tags/drive/folder.tag      |   6 +-
 src/web/app/mobile/tags/follow-button.tag     |  70 ++--
 src/web/app/mobile/tags/home-timeline.tag     |  46 +--
 src/web/app/mobile/tags/home.tag              |   6 +-
 src/web/app/mobile/tags/images-viewer.tag     |   6 +-
 .../app/mobile/tags/notification-preview.tag  |   4 +-
 src/web/app/mobile/tags/notification.tag      |   4 +-
 src/web/app/mobile/tags/notifications.tag     |  38 +-
 src/web/app/mobile/tags/notify.tag            |  20 +-
 src/web/app/mobile/tags/page/drive.tag        |  50 +--
 src/web/app/mobile/tags/page/entrance.tag     |  20 +-
 src/web/app/mobile/tags/page/home.tag         |  38 +-
 .../app/mobile/tags/page/messaging-room.tag   |  24 +-
 src/web/app/mobile/tags/page/messaging.tag    |  10 +-
 .../app/mobile/tags/page/notifications.tag    |  14 +-
 src/web/app/mobile/tags/page/post.tag         |  20 +-
 src/web/app/mobile/tags/page/search.tag       |  18 +-
 src/web/app/mobile/tags/page/settings.tag     |   6 +-
 src/web/app/mobile/tags/page/settings/api.tag |   6 +-
 .../tags/page/settings/authorized-apps.tag    |   6 +-
 .../app/mobile/tags/page/settings/signin.tag  |   6 +-
 .../app/mobile/tags/page/settings/twitter.tag |   6 +-
 .../app/mobile/tags/page/user-followers.tag   |  34 +-
 .../app/mobile/tags/page/user-following.tag   |  34 +-
 src/web/app/mobile/tags/page/user.tag         |  18 +-
 src/web/app/mobile/tags/post-detail.tag       | 118 +++---
 src/web/app/mobile/tags/post-form.tag         | 108 +++---
 src/web/app/mobile/tags/post-preview.tag      |   2 +-
 src/web/app/mobile/tags/search-posts.tag      |  22 +-
 src/web/app/mobile/tags/search.tag            |   8 +-
 src/web/app/mobile/tags/stream-indicator.tag  |  30 +-
 src/web/app/mobile/tags/sub-post-content.tag  |  12 +-
 src/web/app/mobile/tags/timeline-post-sub.tag |   2 +-
 src/web/app/mobile/tags/timeline-post.tag     |  54 +--
 src/web/app/mobile/tags/timeline.tag          |  46 +--
 src/web/app/mobile/tags/ui-header.tag         |  16 +-
 src/web/app/mobile/tags/ui-nav.tag            |  12 +-
 src/web/app/mobile/tags/ui.tag                |  36 +-
 src/web/app/mobile/tags/user-followers.tag    |  14 +-
 src/web/app/mobile/tags/user-following.tag    |  14 +-
 src/web/app/mobile/tags/user-preview.tag      |   2 +-
 src/web/app/mobile/tags/user-timeline.tag     |  20 +-
 src/web/app/mobile/tags/user.tag              |  50 +--
 src/web/app/mobile/tags/users-list.tag        |  54 +--
 164 files changed, 2979 insertions(+), 2966 deletions(-)

diff --git a/src/web/app/auth/tags/form.tag b/src/web/app/auth/tags/form.tag
index 99212febf..b5ace7371 100644
--- a/src/web/app/auth/tags/form.tag
+++ b/src/web/app/auth/tags/form.tag
@@ -106,21 +106,21 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@session = @opts.session
-		@app = @session.app
+		this.session = this.opts.session
+		this.app = @session.app
 
-		@cancel = ~>
-			@api \auth/deny do
+		cancel() {
+			this.api 'auth/deny' do
 				token: @session.token
-			.then ~>
-				@trigger \denied
+			.then =>
+				this.trigger('denied');
 
-		@accept = ~>
-			@api \auth/accept do
+		accept() {
+			this.api 'auth/accept' do
 				token: @session.token
-			.then ~>
-				@trigger \accepted
+			.then =>
+				this.trigger('accepted');
 	</script>
 </mk-form>
diff --git a/src/web/app/auth/tags/index.tag b/src/web/app/auth/tags/index.tag
index b17d857db..a9f7828b9 100644
--- a/src/web/app/auth/tags/index.tag
+++ b/src/web/app/auth/tags/index.tag
@@ -88,48 +88,48 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \api
+		this.mixin('i');
+		this.mixin('api');
 
-		@state = null
-		@fetching = true
+		this.state = null
+		this.fetching = true
 
-		@token = window.location.href.split \/ .pop!
+		this.token = window.location.href.split '/' .pop!
 
-		@on \mount ~>
+		this.on('mount', () => {
 			if not @SIGNIN then return
 
-			# Fetch session
-			@api \auth/session/show do
+			// Fetch session
+			this.api 'auth/session/show' do
 				token: @token
-			.then (session) ~>
-				@session = session
-				@fetching = false
+			.then (session) =>
+				this.session = session
+				this.fetching = false
 
-				# 既に連携していた場合
+				// 既に連携していた場合
 				if @session.app.is_authorized
-					@api \auth/accept do
+					this.api 'auth/accept' do
 						token: @session.token
-					.then ~>
+					.then =>
 						@accepted!
 				else
-					@state = \waiting
-					@update!
+					this.state = 'waiting' 
+					this.update();
 
-					@refs.form.on \denied ~>
-						@state = \denied
-						@update!
+					this.refs.form.on('denied', () => {
+						this.state = 'denied' 
+						this.update();
 
-					@refs.form.on \accepted @accepted
+					this.refs.form.on 'accepted' @accepted
 
-			.catch (error) ~>
-				@fetching = false
-				@state = \fetch-session-error
-				@update!
+			.catch (error) =>
+				this.fetching = false
+				this.state = 'fetch-session-error' 
+				this.update();
 
-		@accepted = ~>
-			@state = \accepted
-			@update!
+		accepted() {
+			this.state = 'accepted' 
+			this.update();
 
 			if @session.app.callback_url
 				location.href = @session.app.callback_url + '?token=' + @session.token
diff --git a/src/web/app/common/tags/api-info.tag b/src/web/app/common/tags/api-info.tag
index f3cef2650..d3b1e4c25 100644
--- a/src/web/app/common/tags/api-info.tag
+++ b/src/web/app/common/tags/api-info.tag
@@ -21,6 +21,6 @@
 					text-decoration underline
 	</style>
 	<script>
-		@mixin \i
+		this.mixin('i');
 	</script>
 </mk-api-info>
diff --git a/src/web/app/common/tags/authorized-apps.tag b/src/web/app/common/tags/authorized-apps.tag
index 16e9d9c0c..918e8b956 100644
--- a/src/web/app/common/tags/authorized-apps.tag
+++ b/src/web/app/common/tags/authorized-apps.tag
@@ -17,18 +17,18 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@apps = []
-		@fetching = true
+		this.apps = []
+		this.fetching = true
 
-		@on \mount ~>
-			@api \i/authorized_apps
-			.then (apps) ~>
-				@apps = apps
-				@fetching = false
-				@update!
-			.catch (err) ~>
+		this.on('mount', () => {
+			this.api 'i/authorized_apps' 
+			.then (apps) =>
+				this.apps = apps
+				this.fetching = false
+				this.update();
+			.catch (err) =>
 				console.error err
 	</script>
 </mk-authorized-apps>
diff --git a/src/web/app/common/tags/core-error.tag b/src/web/app/common/tags/core-error.tag
index 5b5d16360..07f41e403 100644
--- a/src/web/app/common/tags/core-error.tag
+++ b/src/web/app/common/tags/core-error.tag
@@ -57,8 +57,8 @@
 
 	</style>
 	<script>
-		@retry = ~>
-			@unmount!
-			@opts.retry!
+		retry() {
+			this.unmount();
+			this.opts.retry!
 	</script>
 </mk-core-error>
diff --git a/src/web/app/common/tags/file-type-icon.tag b/src/web/app/common/tags/file-type-icon.tag
index 37cae4999..c484a5749 100644
--- a/src/web/app/common/tags/file-type-icon.tag
+++ b/src/web/app/common/tags/file-type-icon.tag
@@ -5,6 +5,6 @@
 			display inline
 	</style>
 	<script>
-		@kind = @opts.type.split \/ .0
+		this.kind = this.opts.type.split '/' .0
 	</script>
 </mk-file-type-icon>
diff --git a/src/web/app/common/tags/messaging/form.tag b/src/web/app/common/tags/messaging/form.tag
index d6750fb9e..649c16a25 100644
--- a/src/web/app/common/tags/messaging/form.tag
+++ b/src/web/app/common/tags/messaging/form.tag
@@ -2,9 +2,15 @@
 	<textarea ref="text" onkeypress={ onkeypress } onpaste={ onpaste } placeholder="ここにメッセージを入力"></textarea>
 	<div class="files"></div>
 	<mk-uploader ref="uploader"></mk-uploader>
-	<button class="send" onclick={ send } disabled={ sending } title="メッセージを送信"><i class="fa fa-paper-plane" if={ !sending }></i><i class="fa fa-spinner fa-spin" if={ sending }></i></button>
-	<button class="attach-from-local" type="button" title="PCから画像を添付する"><i class="fa fa-upload"></i></button>
-	<button class="attach-from-drive" type="button" title="アルバムから画像を添付する"><i class="fa fa-folder-open"></i></button>
+	<button class="send" onclick={ send } disabled={ sending } title="メッセージを送信">
+		<i class="fa fa-paper-plane" if={ !sending }></i><i class="fa fa-spinner fa-spin" if={ sending }></i>
+	</button>
+	<button class="attach-from-local" type="button" title="PCから画像を添付する">
+		<i class="fa fa-upload"></i>
+	</button>
+	<button class="attach-from-drive" type="button" title="アルバムから画像を添付する">
+		<i class="fa fa-folder-open"></i>
+	</button>
 	<input name="file" type="file" accept="image/*"/>
 	<style>
 		:scope
@@ -111,49 +117,56 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@onpaste = (e) ~>
-			data = e.clipboard-data
-			items = data.items
-			for i from 0 to items.length - 1
-				item = items[i]
-				switch (item.kind)
-					| \file =>
-						@upload item.get-as-file!
+		onpaste(e) {
+			const data = e.clipboardData;
+			const items = data.items;
+			for (let i = 0; i < items.length; i++) {
+				const item = items[i];
+				if (item.kind == 'file') {
+					this.upload(item.getAsFile());
+				}
+			}
+		}
 
-		@onkeypress = (e) ~>
-			if (e.which == 10 || e.which == 13) && e.ctrl-key
-				@send!
+		onkeypress(e) {
+			if ((e.which == 10 || e.which == 13) && e.ctrlKey) {
+				this.send();
+			}
+		}
 
-		@select-file = ~>
-			@refs.file.click!
+		selectFile() {
+			this.refs.file.click();
+		}
 
-		@select-file-from-drive = ~>
-			browser = document.body.append-child document.create-element \mk-select-file-from-drive-window
-			event = riot.observable!
-			riot.mount browser, do
-				multiple: true
+		selectFileFromDrive() {
+			const browser = document.body.appendChild(document.createElement('mk-select-file-from-drive-window'));
+			const event = riot.observable();
+			riot.mount(browser, {
+				multiple: true,
 				event: event
-			event.one \selected (files) ~>
-				files.for-each @add-file
+			});
+			event.one('selected', files => {
+				files.forEach(this.addFile);
+			});
 
-		@send = ~>
-			@sending = true
-			@api \messaging/messages/create do
-				user_id: @opts.user.id
-				text: @refs.text.value
-			.then (message) ~>
+		send() {
+			this.sending = true
+			this.api 'messaging/messages/create' do
+				user_id: this.opts.user.id
+				text: this.refs.text.value
+			.then (message) =>
 				@clear!
-			.catch (err) ~>
+			.catch (err) =>
 				console.error err
-			.then ~>
-				@sending = false
-				@update!
+			.then =>
+				this.sending = false
+				this.update();
 
-		@clear = ~>
-			@refs.text.value = ''
-			@files = []
-			@update!
+		clear() {
+			this.refs.text.value = ''
+			this.files = []
+			this.update();
 	</script>
 </mk-messaging-form>
diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
index 69f78ba8e..f9ce48641 100644
--- a/src/web/app/common/tags/messaging/index.tag
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -286,72 +286,72 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \api
+		this.mixin('i');
+		this.mixin('api');
 
-		@search-result = []
+		this.search-result = []
 
-		@on \mount ~>
-			@api \messaging/history
-			.then (history) ~>
-				@is-loading = false
-				history.for-each (message) ~>
+		this.on('mount', () => {
+			this.api 'messaging/history' 
+			.then (history) =>
+				this.is-loading = false
+				history.for-each (message) =>
 					message.is_me = message.user_id == @I.id
-					message._click = ~>
+					message._click = =>
 						if message.is_me
-							@trigger \navigate-user message.recipient
+							this.trigger 'navigate-user' message.recipient
 						else
-							@trigger \navigate-user message.user
-				@history = history
-				@update!
-			.catch (err) ~>
+							this.trigger 'navigate-user' message.user
+				this.history = history
+				this.update();
+			.catch (err) =>
 				console.error err
 
-		@search = ~>
-			q = @refs.search.value
+		search() {
+			q = this.refs.search.value
 			if q == ''
-				@search-result = []
+				this.search-result = []
 			else
-				@api \users/search do
+				this.api 'users/search' do
 					query: q
 					max: 5
-				.then (users) ~>
-					users.for-each (user) ~>
-						user._click = ~>
-							@trigger \navigate-user user
-							@search-result = []
-					@search-result = users
-					@update!
-				.catch (err) ~>
+				.then (users) =>
+					users.for-each (user) =>
+						user._click = =>
+							this.trigger 'navigate-user' user
+							this.search-result = []
+					this.search-result = users
+					this.update();
+				.catch (err) =>
 					console.error err
 
-		@on-search-keydown = (e) ~>
+		on-search-keydown(e) {
 			key = e.which
 			switch (key)
-				| 9, 40 => # Key[TAB] or Key[↓]
+				| 9, 40 => // Key[TAB] or Key[↓]
 					e.prevent-default!
 					e.stop-propagation!
-					@refs.search-result.child-nodes[0].focus!
+					this.refs.search-result.child-nodes[0].focus();
 
-		@on-search-result-keydown = (i, e) ~>
+		on-search-result-keydown(i, e) {
 			key = e.which
 			switch (key)
-				| 10, 13 => # Key[ENTER]
+				| 10, 13 => // Key[ENTER]
 					e.prevent-default!
 					e.stop-propagation!
 					@search-result[i]._click!
-				| 27 => # Key[ESC]
+				| 27 => // Key[ESC]
 					e.prevent-default!
 					e.stop-propagation!
-					@refs.search.focus!
-				| 38 => # Key[↑]
+					this.refs.search.focus();
+				| 38 => // Key[↑]
 					e.prevent-default!
 					e.stop-propagation!
-					(@refs.search-result.child-nodes[i].previous-element-sibling || @refs.search-result.child-nodes[@search-result.length - 1]).focus!
-				| 9, 40 => # Key[TAB] or Key[↓]
+					(this.refs.search-result.child-nodes[i].previous-element-sibling || this.refs.search-result.child-nodes[@search-result.length - 1]).focus();
+				| 9, 40 => // Key[TAB] or Key[↓]
 					e.prevent-default!
 					e.stop-propagation!
-					(@refs.search-result.child-nodes[i].next-element-sibling || @refs.search-result.child-nodes[0]).focus!
+					(this.refs.search-result.child-nodes[i].next-element-sibling || this.refs.search-result.child-nodes[0]).focus();
 
 	</script>
 </mk-messaging>
diff --git a/src/web/app/common/tags/messaging/message.tag b/src/web/app/common/tags/messaging/message.tag
index 5765ffa6c..a43991e0e 100644
--- a/src/web/app/common/tags/messaging/message.tag
+++ b/src/web/app/common/tags/messaging/message.tag
@@ -203,27 +203,27 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \text
+		this.mixin('i');
+		this.mixin('text');
 
-		@message = @opts.message
+		this.message = this.opts.message
 		@message.is_me = @message.user.id == @I.id
 
-		@on \mount ~>
+		this.on('mount', () => {
 			if @message.text?
 				tokens = @analyze @message.text
 
-				@refs.text.innerHTML = @compile tokens
+				this.refs.text.innerHTML = @compile tokens
 
-				@refs.text.children.for-each (e) ~>
-					if e.tag-name == \MK-URL
+				this.refs.text.children.for-each (e) =>
+					if e.tag-name == 'MK-URL' 
 						riot.mount e
 
-				# URLをプレビュー
+				// URLをプレビュー
 				tokens
-					.filter (t) -> t.type == \link
-					.map (t) ~>
-						@preview = @refs.text.append-child document.create-element \mk-url-preview
+					.filter (t) -> t.type == 'link' 
+					.map (t) =>
+						this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
 						riot.mount @preview, do
 							url: t.content
 	</script>
diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index 5882a7fa4..a571b330c 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -124,101 +124,101 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \api
-		@mixin \messaging-stream
+		this.mixin('i');
+		this.mixin('api');
+		this.mixin('messaging-stream');
 
-		@user = @opts.user
-		@init = true
-		@sending = false
-		@messages = []
+		this.user = this.opts.user
+		this.init = true
+		this.sending = false
+		this.messages = []
 
-		@connection = new @MessagingStreamConnection @I, @user.id
+		this.connection = new @MessagingStreamConnection @I, @user.id
 
-		@on \mount ~>
-			@connection.event.on \message @on-message
-			@connection.event.on \read @on-read
+		this.on('mount', () => {
+			@connection.event.on 'message' this.on-message
+			@connection.event.on 'read' this.on-read
 
-			document.add-event-listener \visibilitychange @on-visibilitychange
+			document.add-event-listener 'visibilitychange' this.on-visibilitychange
 
-			@api \messaging/messages do
+			this.api 'messaging/messages' do
 				user_id: @user.id
-			.then (messages) ~>
-				@init = false
-				@messages = messages.reverse!
-				@update!
+			.then (messages) =>
+				this.init = false
+				this.messages = messages.reverse!
+				this.update();
 				@scroll-to-bottom!
-			.catch (err) ~>
+			.catch (err) =>
 				console.error err
 
-		@on \unmount ~>
-			@connection.event.off \message @on-message
-			@connection.event.off \read @on-read
+		this.on('unmount', () => {
+			@connection.event.off 'message' this.on-message
+			@connection.event.off 'read' this.on-read
 			@connection.close!
 
-			document.remove-event-listener \visibilitychange @on-visibilitychange
+			document.remove-event-listener 'visibilitychange' this.on-visibilitychange
 
-		@on \update ~>
-			@messages.for-each (message) ~>
+		this.on('update', () => {
+			@messages.for-each (message) =>
 				date = (new Date message.created_at).get-date!
 				month = (new Date message.created_at).get-month! + 1
 				message._date = date
 				message._datetext = month + '月 ' + date + '日'
 
-		@on-message = (message) ~>
+		on-message(message) {
 			is-bottom = @is-bottom!
 
 			@messages.push message
 			if message.user_id != @I.id and not document.hidden
 				@connection.socket.send JSON.stringify do
-					type: \read
+					type: 'read' 
 					id: message.id
-			@update!
+			this.update();
 
 			if is-bottom
-				# Scroll to bottom
+				// Scroll to bottom
 				@scroll-to-bottom!
 			else if message.user_id != @I.id
-				# Notify
+				// Notify
 				@notify '新しいメッセージがあります'
 
-		@on-read = (ids) ~>
+		on-read(ids) {
 			if not Array.isArray ids then ids = [ids]
-			ids.for-each (id) ~>
-				if (@messages.some (x) ~> x.id == id)
+			ids.for-each (id) =>
+				if (@messages.some (x) => x.id == id)
 					exist = (@messages.map (x) -> x.id).index-of id
 					@messages[exist].is_read = true
-					@update!
+					this.update();
 
-		@is-bottom = ~>
-			current = @root.scroll-top + @root.offset-height
-			max = @root.scroll-height
+		is-bottom() {
+			current = this.root.scroll-top + this.root.offset-height
+			max = this.root.scroll-height
 			current > (max - 32)
 
-		@scroll-to-bottom = ~>
-			@root.scroll-top = @root.scroll-height
+		scroll-to-bottom() {
+			this.root.scroll-top = this.root.scroll-height
 
-		@notify = (message) ~>
-			n = document.create-element \p
+		notify(message) {
+			n = document.createElement 'p' 
 			n.inner-HTML = '<i class="fa fa-arrow-circle-down"></i>' + message
-			n.onclick = ~>
+			n.onclick = =>
 				@scroll-to-bottom!
 				n.parent-node.remove-child n
-			@refs.notifications.append-child n
+			this.refs.notifications.appendChild n
 
-			set-timeout ~>
+			setTimeout =>
 				n.style.opacity = 0
-				set-timeout ~>
+				setTimeout =>
 					n.parent-node.remove-child n
 				, 1000ms
 			, 4000ms
 
-		@on-visibilitychange = ~>
+		on-visibilitychange() {
 			if document.hidden then return
-			@messages.for-each (message) ~>
+			@messages.for-each (message) =>
 				if message.user_id != @I.id and not message.is_read
 					@connection.socket.send JSON.stringify do
-						type: \read
+						type: 'read' 
 						id: message.id
 	</script>
 </mk-messaging-room>
diff --git a/src/web/app/common/tags/number.tag b/src/web/app/common/tags/number.tag
index c878c842e..626b184fc 100644
--- a/src/web/app/common/tags/number.tag
+++ b/src/web/app/common/tags/number.tag
@@ -5,14 +5,14 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			# バグ? https://github.com/riot/riot/issues/2103
-			#value = @opts.value
-			value = @opts.riot-value
-			max = @opts.max
+		this.on('mount', () => {
+			// バグ? https://github.com/riot/riot/issues/2103
+			#value = this.opts.value
+			value = this.opts.riot-value
+			max = this.opts.max
 
 			if max? then if value > max then value = max
 
-			@root.innerHTML = value.to-locale-string!
+			this.root.innerHTML = value.to-locale-string!
 	</script>
 </mk-number>
diff --git a/src/web/app/common/tags/poll-editor.tag b/src/web/app/common/tags/poll-editor.tag
index 1c9c668f0..46975bbe2 100644
--- a/src/web/app/common/tags/poll-editor.tag
+++ b/src/web/app/common/tags/poll-editor.tag
@@ -86,24 +86,24 @@
 
 	</style>
 	<script>
-		@choices = ['', '']
+		this.choices = ['', '']
 
-		@oninput = (i, e) ~>
+		oninput(i, e) {
 			@choices[i] = e.target.value
 
-		@add = ~>
+		add() {
 			@choices.push ''
-			@update!
-			@refs.choices.child-nodes[@choices.length - 1].child-nodes[0].focus!
+			this.update();
+			this.refs.choices.child-nodes[@choices.length - 1].child-nodes[0].focus();
 
-		@remove = (i) ~>
-			@choices = @choices.filter((_, _i) -> _i != i)
-			@update!
+		remove(i) {
+			this.choices = @choices.filter((_, _i) -> _i != i)
+			this.update();
 
-		@destroy = ~>
-			@opts.ondestroy!
+		destroy() {
+			this.opts.ondestroy!
 
-		@get = ~>
+		get() {
 			return {
 				choices: @choices.filter (choice) -> choice != ''
 			}
diff --git a/src/web/app/common/tags/poll.tag b/src/web/app/common/tags/poll.tag
index 426bb4428..d0ee1fad7 100644
--- a/src/web/app/common/tags/poll.tag
+++ b/src/web/app/common/tags/poll.tag
@@ -68,23 +68,23 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@post = @opts.post
-		@poll = @post.poll
-		@total = @poll.choices.reduce ((a, b) -> a + b.votes), 0
-		@is-voted = @poll.choices.some (c) -> c.is_voted
-		@result = @is-voted
+		this.post = this.opts.post
+		this.poll = @post.poll
+		this.total = @poll.choices.reduce ((a, b) -> a + b.votes), 0
+		this.is-voted = @poll.choices.some (c) -> c.is_voted
+		this.result = @is-voted
 
-		@toggle-result = ~>
-			@result = !@result
+		toggle-result() {
+			this.result = !@result
 
-		@vote = (id) ~>
+		vote(id) {
 			if (@poll.choices.some (c) -> c.is_voted) then return
-			@api \posts/polls/vote do
+			this.api 'posts/polls/vote' do
 				post_id: @post.id
 				choice: id
-			.then ~>
+			.then =>
 				@poll.choices.for-each (c) ->
 					if c.id == id
 						c.votes++
diff --git a/src/web/app/common/tags/raw.tag b/src/web/app/common/tags/raw.tag
index 609c53e7e..0637675c4 100644
--- a/src/web/app/common/tags/raw.tag
+++ b/src/web/app/common/tags/raw.tag
@@ -4,5 +4,5 @@
 			display inline
 
 	</style>
-	<script>@root.innerHTML = @opts.content</script>
+	<script>this.root.innerHTML = this.opts.content</script>
 </mk-raw>
diff --git a/src/web/app/common/tags/ripple-string.tag b/src/web/app/common/tags/ripple-string.tag
index d3303e6ba..f52d75e70 100644
--- a/src/web/app/common/tags/ripple-string.tag
+++ b/src/web/app/common/tags/ripple-string.tag
@@ -14,13 +14,13 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			text = @root.innerHTML
-			@root.innerHTML = ''
-			(text.split '').for-each (c, i) ~>
-				ce = document.create-element \span
+		this.on('mount', () => {
+			text = this.root.innerHTML
+			this.root.innerHTML = ''
+			(text.split '').for-each (c, i) =>
+				ce = document.createElement 'span' 
 				ce.innerHTML = c
-				ce.style.animation-delay = (i / 10) + 's'
-				@root.append-child ce
+				ce.style.animationDelay = (i / 10) + 's'
+				this.root.appendChild ce
 	</script>
 </mk-ripple-string>
diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag
index ffc837891..2b8bddd26 100644
--- a/src/web/app/common/tags/signin-history.tag
+++ b/src/web/app/common/tags/signin-history.tag
@@ -48,28 +48,28 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \stream
+		this.mixin('api');
+		this.mixin('stream');
 
-		@history = []
-		@fetching = true
+		this.history = []
+		this.fetching = true
 
-		@on \mount ~>
-			@api \i/signin_history
-			.then (history) ~>
-				@history = history
-				@fetching = false
-				@update!
-			.catch (err) ~>
+		this.on('mount', () => {
+			this.api 'i/signin_history' 
+			.then (history) =>
+				this.history = history
+				this.fetching = false
+				this.update();
+			.catch (err) =>
 				console.error err
 
-			@stream.on \signin @on-signin
+			@stream.on 'signin' this.on-signin
 
-		@on \unmount ~>
-			@stream.off \signin @on-signin
+		this.on('unmount', () => {
+			@stream.off 'signin' this.on-signin
 
-		@on-signin = (signin) ~>
+		on-signin(signin) {
 			@history.unshift signin
-			@update!
+			this.update();
 	</script>
 </mk-signin-history>
diff --git a/src/web/app/common/tags/signin.tag b/src/web/app/common/tags/signin.tag
index 28d73b037..75fa51afa 100644
--- a/src/web/app/common/tags/signin.tag
+++ b/src/web/app/common/tags/signin.tag
@@ -97,41 +97,41 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@user = null
-		@signing = false
+		this.user = null
+		this.signing = false
 
-		@oninput = ~>
-			@api \users/show do
-				username: @refs.username.value
-			.then (user) ~>
-				@user = user
-				@trigger \user user
-				@update!
+		oninput() {
+			this.api 'users/show' do
+				username: this.refs.username.value
+			.then (user) =>
+				this.user = user
+				this.trigger 'user' user
+				this.update();
 
-		@onsubmit = (e) ~>
+		onsubmit(e) {
 			e.prevent-default!
 
-			if @refs.username.value == ''
-				@refs.username.focus!
+			if this.refs.username.value == ''
+				this.refs.username.focus();
 				return false
-			if @refs.password.value == ''
-				@refs.password.focus!
+			if this.refs.password.value == ''
+				this.refs.password.focus();
 				return false
 
-			@signing = true
-			@update!
+			this.signing = true
+			this.update();
 
-			@api \signin do
-				username: @refs.username.value
-				password: @refs.password.value
-			.then ~>
+			this.api 'signin' do
+				username: this.refs.username.value
+				password: this.refs.password.value
+			.then =>
 				location.reload!
-			.catch ~>
+			.catch =>
 				alert 'something happened'
-				@signing = false
-				@update!
+				this.signing = false
+				this.update();
 
 			false
 	</script>
diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag
index 7af72807a..86c4bb5e1 100644
--- a/src/web/app/common/tags/signup.tag
+++ b/src/web/app/common/tags/signup.tag
@@ -174,117 +174,117 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \get-password-strength
+		this.mixin('api');
+		this.mixin('get-password-strength');
 
-		@username-state = null
-		@password-strength = ''
-		@password-retype-state = null
-		@recaptchaed = false
+		this.username-state = null
+		this.password-strength = ''
+		this.password-retype-state = null
+		this.recaptchaed = false
 
-		window.on-recaptchaed = ~>
-			@recaptchaed = true
-			@update!
+		window.on-recaptchaed = =>
+			this.recaptchaed = true
+			this.update();
 
-		window.on-recaptcha-expired = ~>
-			@recaptchaed = false
-			@update!
+		window.on-recaptcha-expired = =>
+			this.recaptchaed = false
+			this.update();
 
-		@on \mount ~>
-			head = (document.get-elements-by-tag-name \head).0
-			script = document.create-element \script
-				..set-attribute \src \https://www.google.com/recaptcha/api.js
-			head.append-child script
+		this.on('mount', () => {
+			head = (document.get-elements-by-tag-name 'head).0' 
+			script = document.createElement 'script' 
+				..set-attribute 'src' \https://www.google.com/recaptcha/api.js
+			head.appendChild script
 
-		@on-change-username = ~>
-			username = @refs.username.value
+		on-change-username() {
+			username = this.refs.username.value
 
 			if username == ''
-				@username-state = null
-				@update!
+				this.username-state = null
+				this.update();
 				return
 
 			err = switch
-				| not username.match /^[a-zA-Z0-9\-]+$/ => \invalid-format
-				| username.length < 3chars              => \min-range
-				| username.length > 20chars             => \max-range
+				| not username.match /^[a-zA-Z0-9\-]+$/ => 'invalid-format' 
+				| username.length < 3chars              => 'min-range' 
+				| username.length > 20chars             => 'max-range' 
 				| _                                     => null
 
 			if err?
-				@username-state = err
-				@update!
+				this.username-state = err
+				this.update();
 			else
-				@username-state = \wait
-				@update!
+				this.username-state = 'wait' 
+				this.update();
 
-				@api \username/available do
+				this.api 'username/available' do
 					username: username
-				.then (result) ~>
+				.then (result) =>
 					if result.available
-						@username-state = \ok
+						this.username-state = 'ok' 
 					else
-						@username-state = \unavailable
-					@update!
-				.catch (err) ~>
-					@username-state = \error
-					@update!
+						this.username-state = 'unavailable' 
+					this.update();
+				.catch (err) =>
+					this.username-state = 'error' 
+					this.update();
 
-		@on-change-password = ~>
-			password = @refs.password.value
+		on-change-password() {
+			password = this.refs.password.value
 
 			if password == ''
-				@password-strength = ''
+				this.password-strength = ''
 				return
 
 			strength = @get-password-strength password
 
 			if strength > 0.3
-				@password-strength = \medium
+				this.password-strength = 'medium' 
 				if strength > 0.7
-					@password-strength = \high
+					this.password-strength = 'high' 
 			else
-				@password-strength = \low
+				this.password-strength = 'low' 
 
-			@update!
+			this.update();
 
-			@refs.password-metar.style.width = (strength * 100) + \%
+			this.refs.password-metar.style.width = (strength * 100) + '%' 
 
-		@on-change-password-retype = ~>
-			password = @refs.password.value
-			retyped-password = @refs.password-retype.value
+		on-change-password-retype() {
+			password = this.refs.password.value
+			retyped-password = this.refs.password-retype.value
 
 			if retyped-password == ''
-				@password-retype-state = null
+				this.password-retype-state = null
 				return
 
 			if password == retyped-password
-				@password-retype-state = \match
+				this.password-retype-state = 'match' 
 			else
-				@password-retype-state = \not-match
+				this.password-retype-state = 'not-match' 
 
-		@onsubmit = (e) ~>
+		onsubmit(e) {
 			e.prevent-default!
 
-			username = @refs.username.value
-			password = @refs.password.value
+			username = this.refs.username.value
+			password = this.refs.password.value
 
-			locker = document.body.append-child document.create-element \mk-locker
+			locker = document.body.appendChild document.createElement 'mk-locker' 
 
-			@api \signup do
+			this.api 'signup' do
 				username: username
 				password: password
 				'g-recaptcha-response': grecaptcha.get-response!
-			.then ~>
-				@api \signin do
+			.then =>
+				this.api 'signin' do
 					username: username
 					password: password
-				.then ~>
+				.then =>
 					location.href = CONFIG.url
-			.catch ~>
+			.catch =>
 				alert '何らかの原因によりアカウントの作成に失敗しました。再度お試しください。'
 
 				grecaptcha.reset!
-				@recaptchaed = false
+				this.recaptchaed = false
 
 				locker.parent-node.remove-child locker
 
diff --git a/src/web/app/common/tags/special-message.tag b/src/web/app/common/tags/special-message.tag
index 53c54c981..8304f87ec 100644
--- a/src/web/app/common/tags/special-message.tag
+++ b/src/web/app/common/tags/special-message.tag
@@ -21,7 +21,7 @@
 	</style>
 	<script>
 		now = new Date!
-		@d = now.get-date!
-		@m = now.get-month! + 1
+		this.d = now.get-date!
+		this.m = now.get-month! + 1
 	</script>
 </mk-special-message>
diff --git a/src/web/app/common/tags/time.tag b/src/web/app/common/tags/time.tag
index 0c9a6d6f9..9bdb7f4cd 100644
--- a/src/web/app/common/tags/time.tag
+++ b/src/web/app/common/tags/time.tag
@@ -1,31 +1,31 @@
 <mk-time>
 	<time datetime={ opts.time }><span if={ mode == 'relative' }>{ relative }</span><span if={ mode == 'absolute' }>{ absolute }</span><span if={ mode == 'detail' }>{ absolute } ({ relative })</span></time>
 	<script>
-		@time = new Date @opts.time
-		@mode = @opts.mode || \relative
-		@tickid = null
+		this.time = new Date this.opts.time
+		this.mode = this.opts.mode || 'relative' 
+		this.tickid = null
 
-		@absolute =
-			@time.get-full-year! + \年 +
-			@time.get-month! + 1 + \月 +
-			@time.get-date!      + \日 +
+		this.absolute = 
+			@time.get-full-year! + '年' +
+			@time.get-month! + 1 + '月' +
+			@time.get-date!      + '日' +
 			' ' +
-			@time.get-hours!     + \時 +
-			@time.get-minutes!   + \分
+			@time.get-hours!     + '時' +
+			@time.get-minutes!   + '分' 
 
-		@on \mount ~>
-			if @mode == \relative or @mode == \detail
+		this.on('mount', () => {
+			if @mode == 'relative' or @mode == 'detail' 
 				@tick!
-				@tickid = set-interval @tick, 1000ms
+				this.tickid = set-interval @tick, 1000ms
 
-		@on \unmount ~>
-			if @mode == \relative or @mode == \detail
+		this.on('unmount', () => {
+			if @mode == 'relative' or @mode == 'detail' 
 				clear-interval @tickid
 
-		@tick = ~>
+		tick() {
 			now = new Date!
 			ago = (now - @time) / 1000ms
-			@relative = switch
+			this.relative = switch
 				| ago >= 31536000s => ~~(ago / 31536000s) + '年前'
 				| ago >= 2592000s  => ~~(ago / 2592000s)  + 'ヶ月前'
 				| ago >= 604800s   => ~~(ago / 604800s)   + '週間前'
@@ -36,6 +36,6 @@
 				| ago >= 0s        =>                       'たった今'
 				| ago <  0s        =>                       '未来'
 				| _                =>                       'なぞのじかん'
-			@update!
+			this.update();
 	</script>
 </mk-time>
diff --git a/src/web/app/common/tags/twitter-setting.tag b/src/web/app/common/tags/twitter-setting.tag
index 162ccd292..6996c45b4 100644
--- a/src/web/app/common/tags/twitter-setting.tag
+++ b/src/web/app/common/tags/twitter-setting.tag
@@ -24,6 +24,6 @@
 				color #8899a6
 	</style>
 	<script>
-		@mixin \i
+		this.mixin('i');
 	</script>
 </mk-twitter-setting>
diff --git a/src/web/app/common/tags/uploader.tag b/src/web/app/common/tags/uploader.tag
index 275a26c01..2cf1aa324 100644
--- a/src/web/app/common/tags/uploader.tag
+++ b/src/web/app/common/tags/uploader.tag
@@ -140,55 +140,55 @@
 
 	</style>
 	<script>
-		@mixin \i
+		this.mixin('i');
 
-		@uploads = []
+		this.uploads = []
 
 		
-		@upload = (file, folder) ~>
+		upload(file, folder) {
 			id = Math.random!
 
 			ctx =
 				id: id
-				name: file.name || \untitled
+				name: file.name || 'untitled' 
 				progress: undefined
 
 			@uploads.push ctx
-			@trigger \change-uploads @uploads
-			@update!
+			this.trigger 'change-uploads' @uploads
+			this.update();
 
 			reader = new FileReader!
-			reader.onload = (e) ~>
+			reader.onload = (e) =>
 				ctx.img = e.target.result
-				@update!
+				this.update();
 			reader.read-as-data-URL file
 
 			data = new FormData!
-			data.append \i @I.token
-			data.append \file file
+			data.append 'i' @I.token
+			data.append 'file' file
 
 			if folder?
-				data.append \folder_id folder
+				data.append 'folder_id' folder
 
 			xhr = new XMLHttpRequest!
-			xhr.open \POST CONFIG.apiUrl + '/drive/files/create' true
-			xhr.onload = (e) ~>
+			xhr.open 'POST' CONFIG.apiUrl + '/drive/files/create' true
+			xhr.onload = (e) =>
 				drive-file = JSON.parse e.target.response
 
-				@trigger \uploaded drive-file
+				this.trigger 'uploaded' drive-file
 
-				@uploads = @uploads.filter (x) -> x.id != id
-				@trigger \change-uploads @uploads
+				this.uploads = @uploads.filter (x) -> x.id != id
+				this.trigger 'change-uploads' @uploads
 
-				@update!
+				this.update();
 
-			xhr.upload.onprogress = (e) ~>
+			xhr.upload.onprogress = (e) =>
 				if e.length-computable
 					if ctx.progress == undefined
 						ctx.progress = {}
 					ctx.progress.max = e.total
 					ctx.progress.value = e.loaded
-					@update!
+					this.update();
 
 			xhr.send data
 	</script>
diff --git a/src/web/app/common/tags/url-preview.tag b/src/web/app/common/tags/url-preview.tag
index 7aab9d94e..74f952016 100644
--- a/src/web/app/common/tags/url-preview.tag
+++ b/src/web/app/common/tags/url-preview.tag
@@ -91,22 +91,22 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@url = @opts.url
-		@loading = true
+		this.url = this.opts.url
+		this.loading = true
 
-		@on \mount ~>
+		this.on('mount', () => {
 			fetch CONFIG.url + '/api:url?url=' + @url
-			.then (res) ~>
+			.then (res) =>
 				info <~ res.json!.then
-				@title = info.title
-				@description = info.description
-				@thumbnail = info.thumbnail
-				@icon = info.icon
-				@sitename = info.sitename
+				this.title = info.title
+				this.description = info.description
+				this.thumbnail = info.thumbnail
+				this.icon = info.icon
+				this.sitename = info.sitename
 
-				@loading = false
-				@update!
+				this.loading = false
+				this.update();
 	</script>
 </mk-url-preview>
diff --git a/src/web/app/common/tags/url.tag b/src/web/app/common/tags/url.tag
index d4284b61b..596d2914c 100644
--- a/src/web/app/common/tags/url.tag
+++ b/src/web/app/common/tags/url.tag
@@ -30,19 +30,19 @@
 
 	</style>
 	<script>
-		@url = @opts.href
+		this.url = this.opts.href
 
-		@on \before-mount ~>
-			parser = document.create-element \a
+		this.on('before-mount', () => {
+			parser = document.createElement 'a' 
 			parser.href = @url
 
-			@schema = parser.protocol
-			@hostname = parser.hostname
-			@port = parser.port
-			@pathname = parser.pathname
-			@query = parser.search
-			@hash = parser.hash
+			this.schema = parser.protocol
+			this.hostname = parser.hostname
+			this.port = parser.port
+			this.pathname = parser.pathname
+			this.query = parser.search
+			this.hash = parser.hash
 
-			@update!
+			this.update();
 	</script>
 </mk-url>
diff --git a/src/web/app/desktop/tags/analog-clock.tag b/src/web/app/desktop/tags/analog-clock.tag
index d2458a778..06896fe20 100644
--- a/src/web/app/desktop/tags/analog-clock.tag
+++ b/src/web/app/desktop/tags/analog-clock.tag
@@ -9,29 +9,29 @@
 
 	</style>
 	<script>
-		@on \mount ~>
+		this.on('mount', () => {
 			@draw!
-			@clock = set-interval @draw, 1000ms
+			this.clock = set-interval @draw, 1000ms
 
-		@on \unmount ~>
+		this.on('unmount', () => {
 			clear-interval @clock
 
-		@draw = ~>
+		draw() {
 			now = new Date!
 			s = now.get-seconds!
 			m = now.get-minutes!
 			h = now.get-hours!
 
 			vec2 = (x, y) ->
-				@x = x
-				@y = y
+				this.x = x
+				this.y = y
 
-			ctx = @refs.canvas.get-context \2d
-			canv-w = @refs.canvas.width
-			canv-h = @refs.canvas.height
+			ctx = this.refs.canvas.get-context '2d' 
+			canv-w = this.refs.canvas.width
+			canv-h = this.refs.canvas.height
 			ctx.clear-rect 0, 0, canv-w, canv-h
 
-			# 背景
+			// 背景
 			center = (Math.min (canv-w / 2), (canv-h / 2))
 			line-start = center * 0.90
 			line-end-short = center * 0.87
@@ -56,12 +56,12 @@
 						(canv-h / 2) + uv.y * line-end-short
 				ctx.stroke!
 
-			# 分
+			// 分
 			angle = Math.PI * (m + s / 60) / 30
 			length = (Math.min canv-w, canv-h) / 2.6
 			uv = new vec2 (Math.sin angle), (-Math.cos angle)
 			ctx.begin-path!
-			ctx.stroke-style = \#ffffff
+			ctx.stroke-style = '#ffffff' 
 			ctx.line-width = 2
 			ctx.move-to do
 				(canv-w / 2) - uv.x * length / 5
@@ -71,12 +71,12 @@
 				(canv-h / 2) + uv.y * length
 			ctx.stroke!
 
-			# 時
+			// 時
 			angle = Math.PI * (h % 12 + m / 60) / 6
 			length = (Math.min canv-w, canv-h) / 4
 			uv = new vec2 (Math.sin angle), (-Math.cos angle)
 			ctx.begin-path!
-			#ctx.stroke-style = \#ffffff
+			#ctx.stroke-style = '#ffffff' 
 			ctx.stroke-style = CONFIG.theme-color
 			ctx.line-width = 2
 			ctx.move-to do
@@ -87,7 +87,7 @@
 				(canv-h / 2) + uv.y * length
 			ctx.stroke!
 
-			# 秒
+			// 秒
 			angle = Math.PI * s / 30
 			length = (Math.min canv-w, canv-h) / 2.6
 			uv = new vec2 (Math.sin angle), (-Math.cos angle)
diff --git a/src/web/app/desktop/tags/autocomplete-suggestion.tag b/src/web/app/desktop/tags/autocomplete-suggestion.tag
index 4aea8d888..073352b19 100644
--- a/src/web/app/desktop/tags/autocomplete-suggestion.tag
+++ b/src/web/app/desktop/tags/autocomplete-suggestion.tag
@@ -80,101 +80,101 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@q = @opts.q
-		@textarea = @opts.textarea
-		@loading = true
-		@users = []
-		@select = -1
+		this.q = this.opts.q
+		this.textarea = this.opts.textarea
+		this.loading = true
+		this.users = []
+		this.select = -1
 
-		@on \mount ~>
-			@textarea.add-event-listener \keydown @on-keydown
+		this.on('mount', () => {
+			@textarea.add-event-listener 'keydown' this.on-keydown
 
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) ~>
-				el.add-event-listener \mousedown @mousedown
+			Array.prototype.for-each.call all, (el) =>
+				el.add-event-listener 'mousedown' @mousedown
 
-			@api \users/search_by_username do
+			this.api 'users/search_by_username' do
 				query: @q
 				limit: 30users
-			.then (users) ~>
-				@users = users
-				@loading = false
-				@update!
-			.catch (err) ~>
+			.then (users) =>
+				this.users = users
+				this.loading = false
+				this.update();
+			.catch (err) =>
 				console.error err
 
-		@on \unmount ~>
-			@textarea.remove-event-listener \keydown @on-keydown
+		this.on('unmount', () => {
+			@textarea.remove-event-listener 'keydown' this.on-keydown
 
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) ~>
-				el.remove-event-listener \mousedown @mousedown
+			Array.prototype.for-each.call all, (el) =>
+				el.remove-event-listener 'mousedown' @mousedown
 
-		@mousedown = (e) ~>
-			if (!contains @root, e.target) and (@root != e.target)
+		mousedown(e) {
+			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 
-		@on-click = (e) ~>
+		on-click(e) {
 			@complete e.item
 
-		@on-keydown = (e) ~>
+		on-keydown(e) {
 			key = e.which
 			switch (key)
-				| 10, 13 => # Key[ENTER]
+				| 10, 13 => // Key[ENTER]
 					if @select != -1
 						e.prevent-default!
 						e.stop-propagation!
 						@complete @users[@select]
 					else
 						@close!
-				| 27 => # Key[ESC]
+				| 27 => // Key[ESC]
 					e.prevent-default!
 					e.stop-propagation!
 					@close!
-				| 38 => # Key[↑]
+				| 38 => // Key[↑]
 					if @select != -1
 						e.prevent-default!
 						e.stop-propagation!
 						@select-prev!
 					else
 						@close!
-				| 9, 40 => # Key[TAB] or Key[↓]
+				| 9, 40 => // Key[TAB] or Key[↓]
 					e.prevent-default!
 					e.stop-propagation!
 					@select-next!
 				| _ =>
 					@close!
 
-		@select-next = ~>
+		select-next() {
 			@select++
 
 			if @select >= @users.length
-				@select = 0
+				this.select = 0
 
 			@apply-select!
 
-		@select-prev = ~>
+		select-prev() {
 			@select--
 
 			if @select < 0
-				@select = @users.length - 1
+				this.select = @users.length - 1
 
 			@apply-select!
 
-		@apply-select = ~>
-			@refs.users.children.for-each (el) ~>
-				el.remove-attribute \data-selected
+		apply-select() {
+			this.refs.users.children.for-each (el) =>
+				el.remove-attribute 'data-selected' 
 
-			@refs.users.children[@select].set-attribute \data-selected \true
-			@refs.users.children[@select].focus!
+			this.refs.users.children[@select].set-attribute 'data-selected' \true
+			this.refs.users.children[@select].focus();
 
-		@complete = (user) ~>
-			@opts.complete user
+		complete(user) {
+			this.opts.complete user
 
-		@close = ~>
-			@opts.close!
+		close() {
+			this.opts.close!
 
 		function contains(parent, child)
 			node = child.parent-node
diff --git a/src/web/app/desktop/tags/big-follow-button.tag b/src/web/app/desktop/tags/big-follow-button.tag
index dfee12b2a..6c87e8755 100644
--- a/src/web/app/desktop/tags/big-follow-button.tag
+++ b/src/web/app/desktop/tags/big-follow-button.tag
@@ -70,58 +70,58 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
-		@mixin \stream
+		this.mixin('api');
+		this.mixin('is-promise');
+		this.mixin('stream');
 
-		@user = null
-		@user-promise = if @is-promise @opts.user then @opts.user else Promise.resolve @opts.user
-		@init = true
-		@wait = false
+		this.user = null
+		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
+		this.init = true
+		this.wait = false
 
-		@on \mount ~>
-			@user-promise.then (user) ~>
-				@user = user
-				@init = false
-				@update!
-				@stream.on \follow @on-stream-follow
-				@stream.on \unfollow @on-stream-unfollow
+		this.on('mount', () => {
+			@user-promise.then (user) =>
+				this.user = user
+				this.init = false
+				this.update();
+				@stream.on 'follow' this.on-stream-follow
+				@stream.on 'unfollow' this.on-stream-unfollow
 
-		@on \unmount ~>
-			@stream.off \follow @on-stream-follow
-			@stream.off \unfollow @on-stream-unfollow
+		this.on('unmount', () => {
+			@stream.off 'follow' this.on-stream-follow
+			@stream.off 'unfollow' this.on-stream-unfollow
 
-		@on-stream-follow = (user) ~>
+		on-stream-follow(user) {
 			if user.id == @user.id
-				@user = user
-				@update!
+				this.user = user
+				this.update();
 
-		@on-stream-unfollow = (user) ~>
+		on-stream-unfollow(user) {
 			if user.id == @user.id
-				@user = user
-				@update!
+				this.user = user
+				this.update();
 
-		@onclick = ~>
-			@wait = true
+		onclick() {
+			this.wait = true
 			if @user.is_following
-				@api \following/delete do
+				this.api 'following/delete' do
 					user_id: @user.id
-				.then ~>
+				.then =>
 					@user.is_following = false
 				.catch (err) ->
 					console.error err
-				.then ~>
-					@wait = false
-					@update!
+				.then =>
+					this.wait = false
+					this.update();
 			else
-				@api \following/create do
+				this.api 'following/create' do
 					user_id: @user.id
-				.then ~>
+				.then =>
 					@user.is_following = true
 				.catch (err) ->
 					console.error err
-				.then ~>
-					@wait = false
-					@update!
+				.then =>
+					this.wait = false
+					this.update();
 	</script>
 </mk-big-follow-button>
diff --git a/src/web/app/desktop/tags/contextmenu.tag b/src/web/app/desktop/tags/contextmenu.tag
index b22948b7d..114d48cf3 100644
--- a/src/web/app/desktop/tags/contextmenu.tag
+++ b/src/web/app/desktop/tags/contextmenu.tag
@@ -94,39 +94,39 @@
 
 	</style>
 	<script>
-		@root.add-event-listener \contextmenu (e) ~>
+		this.root.add-event-listener 'contextmenu' (e) =>
 			e.prevent-default!
 
-		@mousedown = (e) ~>
+		mousedown(e) {
 			e.prevent-default!
-			if (!contains @root, e.target) and (@root != e.target)
+			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 			return false
 
-		@open = (pos) ~>
+		open(pos) {
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) ~>
-				el.add-event-listener \mousedown @mousedown
-			@root.style.display = \block
-			@root.style.left = pos.x + \px
-			@root.style.top = pos.y + \px
+			Array.prototype.for-each.call all, (el) =>
+				el.add-event-listener 'mousedown' @mousedown
+			this.root.style.display = 'block' 
+			this.root.style.left = pos.x + 'px' 
+			this.root.style.top = pos.y + 'px' 
 
-			Velocity @root, \finish true
-			Velocity @root, { opacity: 0 } 0ms
-			Velocity @root, {
+			Velocity this.root, 'finish' true
+			Velocity this.root, { opacity: 0 } 0ms
+			Velocity this.root, {
 				opacity: 1
 			} {
 				queue: false
 				duration: 100ms
-				easing: \linear
+				easing: 'linear' 
 			}
 
-		@close = ~>
+		close() {
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) ~>
-				el.remove-event-listener \mousedown @mousedown
-			@trigger \closed
-			@unmount!
+			Array.prototype.for-each.call all, (el) =>
+				el.remove-event-listener 'mousedown' @mousedown
+			this.trigger('closed');
+			this.unmount();
 
 		function contains(parent, child)
 			node = child.parent-node
diff --git a/src/web/app/desktop/tags/crop-window.tag b/src/web/app/desktop/tags/crop-window.tag
index 8d27f4c51..e022c76fa 100644
--- a/src/web/app/desktop/tags/crop-window.tag
+++ b/src/web/app/desktop/tags/crop-window.tag
@@ -158,31 +158,31 @@
 
 	</style>
 	<script>
-		@mixin \cropper
+		this.mixin('cropper');
 
-		@image = @opts.file
-		@title = @opts.title
-		@aspect-ratio = @opts.aspect-ratio
-		@cropper = null
+		this.image = this.opts.file
+		this.title = this.opts.title
+		this.aspect-ratio = this.opts.aspect-ratio
+		this.cropper = null
 
-		@on \mount ~>
-			@img = @refs.window.refs.img
-			@cropper = new @Cropper @img, do
+		this.on('mount', () => {
+			this.img = this.refs.window.refs.img
+			this.cropper = new @Cropper @img, do
 				aspect-ratio: @aspect-ratio
 				highlight: no
 				view-mode: 1
 
-		@ok = ~>
-			@cropper.get-cropped-canvas!.to-blob (blob) ~>
-				@trigger \cropped blob
-				@refs.window.close!
+		ok() {
+			@cropper.get-cropped-canvas!.to-blob (blob) =>
+				this.trigger 'cropped' blob
+				this.refs.window.close!
 
-		@skip = ~>
-			@trigger \skiped
-			@refs.window.close!
+		skip() {
+			this.trigger('skiped');
+			this.refs.window.close!
 
-		@cancel = ~>
-			@trigger \canceled
-			@refs.window.close!
+		cancel() {
+			this.trigger('canceled');
+			this.refs.window.close!
 	</script>
 </mk-crop-window>
diff --git a/src/web/app/desktop/tags/dialog.tag b/src/web/app/desktop/tags/dialog.tag
index 528779242..a444ac18f 100644
--- a/src/web/app/desktop/tags/dialog.tag
+++ b/src/web/app/desktop/tags/dialog.tag
@@ -79,34 +79,34 @@
 
 	</style>
 	<script>
-		@can-through = if opts.can-through? then opts.can-through else true
-		@opts.buttons.for-each (button) ~>
-			button._onclick = ~>
+		this.can-through = if opts.can-through? then opts.can-through else true
+		this.opts.buttons.for-each (button) =>
+			button._onclick = =>
 				if button.onclick?
 					button.onclick!
 				@close!
 
-		@on \mount ~>
-			@refs.header.innerHTML = @opts.title
-			@refs.body.innerHTML = @opts.text
+		this.on('mount', () => {
+			this.refs.header.innerHTML = this.opts.title
+			this.refs.body.innerHTML = this.opts.text
 
-			@refs.bg.style.pointer-events = \auto
-			Velocity @refs.bg, \finish true
-			Velocity @refs.bg, {
+			this.refs.bg.style.pointer-events = 'auto' 
+			Velocity this.refs.bg, 'finish' true
+			Velocity this.refs.bg, {
 				opacity: 1
 			} {
 				queue: false
 				duration: 100ms
-				easing: \linear
+				easing: 'linear' 
 			}
 
-			Velocity @refs.main, {
+			Velocity this.refs.main, {
 				opacity: 0
 				scale: 1.2
 			} {
 				duration: 0
 			}
-			Velocity @refs.main, {
+			Velocity this.refs.main, {
 				opacity: 1
 				scale: 1
 			} {
@@ -114,34 +114,34 @@
 				easing: [ 0, 0.5, 0.5, 1 ]
 			}
 
-		@close = ~>
-			@refs.bg.style.pointer-events = \none
-			Velocity @refs.bg, \finish true
-			Velocity @refs.bg, {
+		close() {
+			this.refs.bg.style.pointer-events = 'none' 
+			Velocity this.refs.bg, 'finish' true
+			Velocity this.refs.bg, {
 				opacity: 0
 			} {
 				queue: false
 				duration: 300ms
-				easing: \linear
+				easing: 'linear' 
 			}
 
-			@refs.main.style.pointer-events = \none
-			Velocity @refs.main, \finish true
-			Velocity @refs.main, {
+			this.refs.main.style.pointer-events = 'none' 
+			Velocity this.refs.main, 'finish' true
+			Velocity this.refs.main, {
 				opacity: 0
 				scale: 0.8
 			} {
 				queue: false
 				duration: 300ms
 				easing: [ 0.5, -0.5, 1, 0.5 ]
-				complete: ~>
-					@unmount!
+				complete: =>
+					this.unmount();
 			}
 
-		@bg-click = ~>
+		bg-click() {
 			if @can-through
-				if @opts.on-through?
-					@opts.on-through!
+				if this.opts.on-through?
+					this.opts.on-through!
 				@close!
 	</script>
 </mk-dialog>
diff --git a/src/web/app/desktop/tags/donation.tag b/src/web/app/desktop/tags/donation.tag
index 7d0056d36..d92e24e30 100644
--- a/src/web/app/desktop/tags/donation.tag
+++ b/src/web/app/desktop/tags/donation.tag
@@ -47,21 +47,21 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \i
+		this.mixin('api');
+		this.mixin('i');
 
-		@close = (e) ~>
+		close(e) {
 			e.prevent-default!
 			e.stop-propagation!
 
 			@I.data.no_donation = true
 			@I.update!
-			@api \i/appdata/set do
+			this.api 'i/appdata/set' do
 				data: JSON.stringify do
 					no_donation: @I.data.no_donation
 
-			@unmount!
+			this.unmount();
 
-			@parent.parent.set-root-layout!
+			this.parent.parent.set-root-layout!
 	</script>
 </mk-donation>
diff --git a/src/web/app/desktop/tags/drive/base-contextmenu.tag b/src/web/app/desktop/tags/drive/base-contextmenu.tag
index c3a613d32..39e01558d 100644
--- a/src/web/app/desktop/tags/drive/base-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/base-contextmenu.tag
@@ -13,26 +13,26 @@
 		</ul>
 	</mk-contextmenu>
 	<script>
-		@browser = @opts.browser
+		this.browser = this.opts.browser
 
-		@on \mount ~>
-			@refs.ctx.on \closed ~>
-				@trigger \closed
-				@unmount!
+		this.on('mount', () => {
+			this.refs.ctx.on('closed', () => {
+				this.trigger('closed');
+				this.unmount();
 
-		@open = (pos) ~>
-			@refs.ctx.open pos
+		open(pos) {
+			this.refs.ctx.open pos
 
-		@create-folder = ~>
+		create-folder() {
 			@browser.create-folder!
-			@refs.ctx.close!
+			this.refs.ctx.close!
 
-		@upload = ~>
+		upload() {
 			@browser.select-local-file!
-			@refs.ctx.close!
+			this.refs.ctx.close!
 
-		@url-upload = ~>
+		url-upload() {
 			@browser.url-upload!
-			@refs.ctx.close!
+			this.refs.ctx.close!
 	</script>
 </mk-drive-browser-base-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/browser-window.tag b/src/web/app/desktop/tags/drive/browser-window.tag
index c97542789..c36726444 100644
--- a/src/web/app/desktop/tags/drive/browser-window.tag
+++ b/src/web/app/desktop/tags/drive/browser-window.tag
@@ -28,19 +28,19 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@folder = if @opts.folder? then @opts.folder else null
+		this.folder = if this.opts.folder? then this.opts.folder else null
 
-		@on \mount ~>
-			@refs.window.on \closed ~>
-				@unmount!
+		this.on('mount', () => {
+			this.refs.window.on('closed', () => {
+				this.unmount();
 
-			@api \drive .then (info) ~>
+			this.api 'drive' .then (info) =>
 				@update do
 					usage: info.usage / info.capacity * 100
 
-		@close = ~>
-			@refs.window.close!
+		close() {
+			this.refs.window.close!
 	</script>
 </mk-drive-browser-window>
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index 1e8448dab..02c886d14 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -238,211 +238,211 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \dialog
-		@mixin \input-dialog
-		@mixin \stream
+		this.mixin('api');
+		this.mixin('dialog');
+		this.mixin('input-dialog');
+		this.mixin('stream');
 
-		@files = []
-		@folders = []
-		@hierarchy-folders = []
+		this.files = []
+		this.folders = []
+		this.hierarchy-folders = []
 
-		@uploads = []
+		this.uploads = []
 
-		# 現在の階層(フォルダ)
-		# * null でルートを表す
-		@folder = null
+		// 現在の階層(フォルダ)
+		// * null でルートを表す
+		this.folder = null
 
-		@multiple = if @opts.multiple? then @opts.multiple else false
+		this.multiple = if this.opts.multiple? then this.opts.multiple else false
 
-		# ドロップされようとしているか
-		@draghover = false
+		// ドロップされようとしているか
+		this.draghover = false
 
-		# 自信の所有するアイテムがドラッグをスタートさせたか
-		# (自分自身の階層にドロップできないようにするためのフラグ)
-		@is-drag-source = false
+		// 自信の所有するアイテムがドラッグをスタートさせたか
+		// (自分自身の階層にドロップできないようにするためのフラグ)
+		this.is-drag-source = false
 
-		@on \mount ~>
-			@refs.uploader.on \uploaded (file) ~>
+		this.on('mount', () => {
+			this.refs.uploader.on('uploaded', (file) => {
 				@add-file file, true
 
-			@refs.uploader.on \change-uploads (uploads) ~>
-				@uploads = uploads
-				@update!
+			this.refs.uploader.on('change-uploads', (uploads) => {
+				this.uploads = uploads
+				this.update();
 
-			@stream.on \drive_file_created @on-stream-drive-file-created
-			@stream.on \drive_file_updated @on-stream-drive-file-updated
-			@stream.on \drive_folder_created @on-stream-drive-folder-created
-			@stream.on \drive_folder_updated @on-stream-drive-folder-updated
+			@stream.on 'drive_file_created' this.on-stream-drive-file-created
+			@stream.on 'drive_file_updated' this.on-stream-drive-file-updated
+			@stream.on 'drive_folder_created' this.on-stream-drive-folder-created
+			@stream.on 'drive_folder_updated' this.on-stream-drive-folder-updated
 
-			# Riotのバグでnullを渡しても""になる
-			# https://github.com/riot/riot/issues/2080
-			#if @opts.folder?
-			if @opts.folder? and @opts.folder != ''
-				@move @opts.folder
+			// Riotのバグでnullを渡しても""になる
+			// https://github.com/riot/riot/issues/2080
+			#if this.opts.folder?
+			if this.opts.folder? and this.opts.folder != ''
+				@move this.opts.folder
 			else
 				@load!
 
-		@on \unmount ~>
-			@stream.off \drive_file_created @on-stream-drive-file-created
-			@stream.off \drive_file_updated @on-stream-drive-file-updated
-			@stream.off \drive_folder_created @on-stream-drive-folder-created
-			@stream.off \drive_folder_updated @on-stream-drive-folder-updated
+		this.on('unmount', () => {
+			@stream.off 'drive_file_created' this.on-stream-drive-file-created
+			@stream.off 'drive_file_updated' this.on-stream-drive-file-updated
+			@stream.off 'drive_folder_created' this.on-stream-drive-folder-created
+			@stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
 
-		@on-stream-drive-file-created = (file) ~>
+		on-stream-drive-file-created(file) {
 			@add-file file, true
 
-		@on-stream-drive-file-updated = (file) ~>
+		on-stream-drive-file-updated(file) {
 			current = if @folder? then @folder.id else null
 			if current != file.folder_id
 				@remove-file file
 			else
 				@add-file file, true
 
-		@on-stream-drive-folder-created = (folder) ~>
+		on-stream-drive-folder-created(folder) {
 			@add-folder folder, true
 
-		@on-stream-drive-folder-updated = (folder) ~>
+		on-stream-drive-folder-updated(folder) {
 			current = if @folder? then @folder.id else null
 			if current != folder.parent_id
 				@remove-folder folder
 			else
 				@add-folder folder, true
 
-		@onmousedown = (e) ~>
-			if (contains @refs.folders-container, e.target) or (contains @refs.files-container, e.target)
+		onmousedown(e) {
+			if (contains this.refs.folders-container, e.target) or (contains this.refs.files-container, e.target)
 				return true
 
-			rect = @refs.main.get-bounding-client-rect!
+			rect = this.refs.main.get-bounding-client-rect!
 
-			left = e.page-x + @refs.main.scroll-left - rect.left - window.page-x-offset
-			top = e.page-y + @refs.main.scroll-top - rect.top - window.page-y-offset
+			left = e.page-x + this.refs.main.scroll-left - rect.left - window.page-x-offset
+			top = e.page-y + this.refs.main.scroll-top - rect.top - window.page-y-offset
 
-			move = (e) ~>
-				@refs.selection.style.display = \block
+			move = (e) =>
+				this.refs.selection.style.display = 'block' 
 
-				cursor-x = e.page-x + @refs.main.scroll-left - rect.left - window.page-x-offset
-				cursor-y = e.page-y + @refs.main.scroll-top - rect.top - window.page-y-offset
+				cursor-x = e.page-x + this.refs.main.scroll-left - rect.left - window.page-x-offset
+				cursor-y = e.page-y + this.refs.main.scroll-top - rect.top - window.page-y-offset
 				w = cursor-x - left
 				h = cursor-y - top
 
 				if w > 0
-					@refs.selection.style.width = w + \px
-					@refs.selection.style.left = left + \px
+					this.refs.selection.style.width = w + 'px' 
+					this.refs.selection.style.left = left + 'px' 
 				else
-					@refs.selection.style.width = -w + \px
-					@refs.selection.style.left = cursor-x + \px
+					this.refs.selection.style.width = -w + 'px' 
+					this.refs.selection.style.left = cursor-x + 'px' 
 
 				if h > 0
-					@refs.selection.style.height = h + \px
-					@refs.selection.style.top = top + \px
+					this.refs.selection.style.height = h + 'px' 
+					this.refs.selection.style.top = top + 'px' 
 				else
-					@refs.selection.style.height = -h + \px
-					@refs.selection.style.top = cursor-y + \px
+					this.refs.selection.style.height = -h + 'px' 
+					this.refs.selection.style.top = cursor-y + 'px' 
 
-			up = (e) ~>
-				document.document-element.remove-event-listener \mousemove move
-				document.document-element.remove-event-listener \mouseup up
+			up = (e) =>
+				document.document-element.remove-event-listener 'mousemove' move
+				document.document-element.remove-event-listener 'mouseup' up
 
-				@refs.selection.style.display = \none
+				this.refs.selection.style.display = 'none' 
 
-			document.document-element.add-event-listener \mousemove move
-			document.document-element.add-event-listener \mouseup up
+			document.document-element.add-event-listener 'mousemove' move
+			document.document-element.add-event-listener 'mouseup' up
 
-		@path-oncontextmenu = (e) ~>
+		path-oncontextmenu(e) {
 			e.prevent-default!
 			e.stop-immediate-propagation!
 			return false
 
-		@ondragover = (e) ~>
+		ondragover(e) {
 			e.prevent-default!
 			e.stop-propagation!
 
-			# ドラッグ元が自分自身の所有するアイテムかどうか
+			// ドラッグ元が自分自身の所有するアイテムかどうか
 			if !@is-drag-source
-				# ドラッグされてきたものがファイルだったら
-				if e.data-transfer.effect-allowed == \all
-					e.data-transfer.drop-effect = \copy
+				// ドラッグされてきたものがファイルだったら
+				if e.data-transfer.effect-allowed == 'all' 
+					e.data-transfer.drop-effect = 'copy' 
 				else
-					e.data-transfer.drop-effect = \move
-				@draghover = true
+					e.data-transfer.drop-effect = 'move' 
+				this.draghover = true
 			else
-				# 自分自身にはドロップさせない
-				e.data-transfer.drop-effect = \none
+				// 自分自身にはドロップさせない
+				e.data-transfer.drop-effect = 'none' 
 			return false
 
-		@ondragenter = (e) ~>
+		ondragenter(e) {
 			e.prevent-default!
 			if !@is-drag-source
-				@draghover = true
+				this.draghover = true
 
-		@ondragleave = (e) ~>
-			@draghover = false
+		ondragleave(e) {
+			this.draghover = false
 
-		@ondrop = (e) ~>
+		ondrop(e) {
 			e.prevent-default!
 			e.stop-propagation!
 
-			@draghover = false
+			this.draghover = false
 
-			# ドロップされてきたものがファイルだったら
+			// ドロップされてきたものがファイルだったら
 			if e.data-transfer.files.length > 0
-				Array.prototype.for-each.call e.data-transfer.files, (file) ~>
+				Array.prototype.for-each.call e.data-transfer.files, (file) =>
 					@upload file, @folder
 				return false
 
-			# データ取得
+			// データ取得
 			data = e.data-transfer.get-data 'text'
 			if !data?
 				return false
 
-			# パース
+			// パース
 			obj = JSON.parse data
 
-			# (ドライブの)ファイルだったら
-			if obj.type == \file
+			// (ドライブの)ファイルだったら
+			if obj.type == 'file' 
 				file = obj.id
-				if (@files.some (f) ~> f.id == file)
+				if (@files.some (f) => f.id == file)
 					return false
 				@remove-file file
-				@api \drive/files/update do
+				this.api 'drive/files/update' do
 					file_id: file
 					folder_id: if @folder? then @folder.id else null
-				.then ~>
-					# something
-				.catch (err, text-status) ~>
+				.then =>
+					// something
+				.catch (err, text-status) =>
 					console.error err
 
-			# (ドライブの)フォルダーだったら
-			else if obj.type == \folder
+			// (ドライブの)フォルダーだったら
+			else if obj.type == 'folder' 
 				folder = obj.id
-				# 移動先が自分自身ならreject
+				// 移動先が自分自身ならreject
 				if @folder? and folder == @folder.id
 					return false
-				if (@folders.some (f) ~> f.id == folder)
+				if (@folders.some (f) => f.id == folder)
 					return false
 				@remove-folder folder
-				@api \drive/folders/update do
+				this.api 'drive/folders/update' do
 					folder_id: folder
 					parent_id: if @folder? then @folder.id else null
-				.then ~>
-					# something
-				.catch (err) ~>
+				.then =>
+					// something
+				.catch (err) =>
 					if err == 'detected-circular-definition'
 						@dialog do
 							'<i class="fa fa-exclamation-triangle"></i>操作を完了できません'
 							'移動先のフォルダーは、移動するフォルダーのサブフォルダーです。'
 							[
-								text: \OK
+								text: 'OK' 
 							]
 
 			return false
 
-		@oncontextmenu = (e) ~>
+		oncontextmenu(e) {
 			e.prevent-default!
 			e.stop-immediate-propagation!
 
-			ctx = document.body.append-child document.create-element \mk-drive-browser-base-contextmenu
+			ctx = document.body.appendChild document.createElement 'mk-drive-browser-base-contextmenu' 
 			ctx = riot.mount ctx, do
 				browser: @
 			ctx = ctx.0
@@ -452,17 +452,17 @@
 
 			return false
 
-		@select-local-file = ~>
-			@refs.file-input.click!
+		select-local-file() {
+			this.refs.file-input.click!
 
-		@url-upload = ~>
+		url-upload() {
 			url <~ @input-dialog do
 				'URLアップロード'
 				'アップロードしたいファイルのURL'
 				null
 
 			if url? and url != ''
-				@api \drive/files/upload_from_url do
+				this.api 'drive/files/upload_from_url' do
 					url: url
 					folder_id: if @folder? then @folder.id else undefined
 
@@ -470,61 +470,61 @@
 					'<i class="fa fa-check"></i>アップロードをリクエストしました'
 					'アップロードが完了するまで時間がかかる場合があります。'
 					[
-						text: \OK
+						text: 'OK' 
 					]
 
-		@create-folder = ~>
+		create-folder() {
 			name <~ @input-dialog do
 				'フォルダー作成'
 				'フォルダー名'
 				null
 
-			@api \drive/folders/create do
+			this.api 'drive/folders/create' do
 				name: name
 				folder_id: if @folder? then @folder.id else undefined
-			.then (folder) ~>
+			.then (folder) =>
 				@add-folder folder, true
-				@update!
-			.catch (err) ~>
+				this.update();
+			.catch (err) =>
 				console.error err
 
-		@change-file-input = ~>
-			files = @refs.file-input.files
+		change-file-input() {
+			files = this.refs.file-input.files
 			for i from 0 to files.length - 1
 				file = files.item i
 				@upload file, @folder
 
-		@upload = (file, folder) ~>
-			if folder? and typeof folder == \object
+		upload(file, folder) {
+			if folder? and typeof folder == 'object' 
 				folder = folder.id
-			@refs.uploader.upload file, folder
+			this.refs.uploader.upload file, folder
 
-		@get-selection = ~>
+		get-selection() {
 			@files.filter (file) -> file._selected
 
-		@new-window = (folder-id) ~>
-			browser = document.body.append-child document.create-element \mk-drive-browser-window
+		new-window(folder-id) {
+			browser = document.body.appendChild document.createElement 'mk-drive-browser-window' 
 			riot.mount browser, do
 				folder: folder-id
 
-		@move = (target-folder) ~>
-			if target-folder? and typeof target-folder == \object
+		move(target-folder) {
+			if target-folder? and typeof target-folder == 'object' 
 				target-folder = target-folder.id
 
 			if target-folder == null
 				@go-root!
 				return
 
-			@loading = true
-			@update!
+			this.loading = true
+			this.update();
 
-			@api \drive/folders/show do
+			this.api 'drive/folders/show' do
 				folder_id: target-folder
-			.then (folder) ~>
-				@folder = folder
-				@hierarchy-folders = []
+			.then (folder) =>
+				this.folder = folder
+				this.hierarchy-folders = []
 
-				x = (f) ~>
+				x = (f) =>
 					@hierarchy-folders.unshift f
 					if f.parent?
 						x f.parent
@@ -532,20 +532,20 @@
 				if folder.parent?
 					x folder.parent
 
-				@update!
+				this.update();
 				@load!
 			.catch (err, text-status) ->
 				console.error err
 
-		@add-folder = (folder, unshift = false) ~>
+		add-folder(folder, unshift = false) {
 			current = if @folder? then @folder.id else null
 			if current != folder.parent_id
 				return
 
-			if (@folders.some (f) ~> f.id == folder.id)
+			if (@folders.some (f) => f.id == folder.id)
 				exist = (@folders.map (f) -> f.id).index-of folder.id
 				@folders[exist] = folder
-				@update!
+				this.update();
 				return
 
 			if unshift
@@ -553,17 +553,17 @@
 			else
 				@folders.push folder
 
-			@update!
+			this.update();
 
-		@add-file = (file, unshift = false) ~>
+		add-file(file, unshift = false) {
 			current = if @folder? then @folder.id else null
 			if current != file.folder_id
 				return
 
-			if (@files.some (f) ~> f.id == file.id)
+			if (@files.some (f) => f.id == file.id)
 				exist = (@files.map (f) -> f.id).index-of file.id
 				@files[exist] = file
-				@update!
+				this.update();
 				return
 
 			if unshift
@@ -571,34 +571,34 @@
 			else
 				@files.push file
 
-			@update!
+			this.update();
 
-		@remove-folder = (folder) ~>
-			if typeof folder == \object
+		remove-folder(folder) {
+			if typeof folder == 'object' 
 				folder = folder.id
-			@folders = @folders.filter (f) -> f.id != folder
-			@update!
+			this.folders = @folders.filter (f) -> f.id != folder
+			this.update();
 
-		@remove-file = (file) ~>
-			if typeof file == \object
+		remove-file(file) {
+			if typeof file == 'object' 
 				file = file.id
-			@files = @files.filter (f) -> f.id != file
-			@update!
+			this.files = @files.filter (f) -> f.id != file
+			this.update();
 
-		@go-root = ~>
+		go-root() {
 			if @folder != null
-				@folder = null
-				@hierarchy-folders = []
-				@update!
+				this.folder = null
+				this.hierarchy-folders = []
+				this.update();
 				@load!
 
-		@load = ~>
-			@folders = []
-			@files = []
-			@more-folders = false
-			@more-files = false
-			@loading = true
-			@update!
+		load() {
+			this.folders = []
+			this.files = []
+			this.more-folders = false
+			this.more-files = false
+			this.loading = true
+			this.update();
 
 			load-folders = null
 			load-files = null
@@ -606,41 +606,41 @@
 			folders-max = 30
 			files-max = 30
 
-			# フォルダ一覧取得
-			@api \drive/folders do
+			// フォルダ一覧取得
+			this.api 'drive/folders' do
 				folder_id: if @folder? then @folder.id else null
 				limit: folders-max + 1
-			.then (folders) ~>
+			.then (folders) =>
 				if folders.length == folders-max + 1
-					@more-folders = true
+					this.more-folders = true
 					folders.pop!
 				load-folders := folders
 				complete!
-			.catch (err, text-status) ~>
+			.catch (err, text-status) =>
 				console.error err
 
-			# ファイル一覧取得
-			@api \drive/files do
+			// ファイル一覧取得
+			this.api 'drive/files' do
 				folder_id: if @folder? then @folder.id else null
 				limit: files-max + 1
-			.then (files) ~>
+			.then (files) =>
 				if files.length == files-max + 1
-					@more-files = true
+					this.more-files = true
 					files.pop!
 				load-files := files
 				complete!
-			.catch (err, text-status) ~>
+			.catch (err, text-status) =>
 				console.error err
 
 			flag = false
-			complete = ~>
+			complete = =>
 				if flag
-					load-folders.for-each (folder) ~>
+					load-folders.for-each (folder) =>
 						@add-folder folder
-					load-files.for-each (file) ~>
+					load-files.for-each (file) =>
 						@add-file file
-					@loading = false
-					@update!
+					this.loading = false
+					this.update();
 				else
 					flag := true
 
diff --git a/src/web/app/desktop/tags/drive/file-contextmenu.tag b/src/web/app/desktop/tags/drive/file-contextmenu.tag
index a2c9eb3f4..69073bd29 100644
--- a/src/web/app/desktop/tags/drive/file-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/file-contextmenu.tag
@@ -38,60 +38,60 @@
 		</ul>
 	</mk-contextmenu>
 	<script>
-		@mixin \api
-		@mixin \i
-		@mixin \update-avatar
-		@mixin \update-banner
-		@mixin \update-wallpaper
-		@mixin \input-dialog
-		@mixin \NotImplementedException
+		this.mixin('api');
+		this.mixin('i');
+		this.mixin('update-avatar');
+		this.mixin('update-banner');
+		this.mixin('update-wallpaper');
+		this.mixin('input-dialog');
+		this.mixin('NotImplementedException');
 
-		@browser = @opts.browser
-		@file = @opts.file
+		this.browser = this.opts.browser
+		this.file = this.opts.file
 
-		@on \mount ~>
-			@refs.ctx.on \closed ~>
-				@trigger \closed
-				@unmount!
+		this.on('mount', () => {
+			this.refs.ctx.on('closed', () => {
+				this.trigger('closed');
+				this.unmount();
 
-		@open = (pos) ~>
-			@refs.ctx.open pos
+		open(pos) {
+			this.refs.ctx.open pos
 
-		@rename = ~>
-			@refs.ctx.close!
+		rename() {
+			this.refs.ctx.close!
 
 			name <~ @input-dialog do
 				'ファイル名の変更'
 				'新しいファイル名を入力してください'
 				@file.name
 
-			@api \drive/files/update do
+			this.api 'drive/files/update' do
 				file_id: @file.id
 				name: name
-			.then ~>
-				# something
-			.catch (err) ~>
+			.then =>
+				// something
+			.catch (err) =>
 				console.error err
 
-		@copy-url = ~>
+		copy-url() {
 			@NotImplementedException!
 
-		@download = ~>
-			@refs.ctx.close!
+		download() {
+			this.refs.ctx.close!
 
-		@set-avatar = ~>
-			@refs.ctx.close!
+		set-avatar() {
+			this.refs.ctx.close!
 			@update-avatar @I, null, @file
 
-		@set-banner = ~>
-			@refs.ctx.close!
+		set-banner() {
+			this.refs.ctx.close!
 			@update-banner @I, null, @file
 
-		@set-wallpaper = ~>
-			@refs.ctx.close!
+		set-wallpaper() {
+			this.refs.ctx.close!
 			@update-wallpaper @I, null, @file
 
-		@add-app = ~>
+		add-app() {
 			@NotImplementedException!
 	</script>
 </mk-drive-browser-file-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/file.tag b/src/web/app/desktop/tags/drive/file.tag
index 252e5ab1d..e86948aee 100644
--- a/src/web/app/desktop/tags/drive/file.tag
+++ b/src/web/app/desktop/tags/drive/file.tag
@@ -144,40 +144,40 @@
 
 	</style>
 	<script>
-		@bytes-to-size = require '../../../common/scripts/bytes-to-size.js'
+		this.bytes-to-size = require('../../../common/scripts/bytes-to-size.js');
 
-		@mixin \i
+		this.mixin('i');
 
-		@file = @opts.file
-		@browser = @parent
+		this.file = this.opts.file
+		this.browser = this.parent
 
-		@title = @file.name + '\n' + @file.type + ' ' + (@bytes-to-size @file.datasize)
+		this.title = @file.name + '\n' + @file.type + ' ' + (@bytes-to-size @file.datasize)
 
-		@is-contextmenu-showing = false
+		this.is-contextmenu-showing = false
 
-		@onclick = ~>
+		onclick() {
 			if @browser.multiple
 				if @file._selected?
 					@file._selected = !@file._selected
 				else
 					@file._selected = true
-				@browser.trigger \change-selection @browser.get-selection!
+				@browser.trigger 'change-selection' @browser.get-selection!
 			else
 				if @file._selected
-					@browser.trigger \selected @file
+					@browser.trigger 'selected' @file
 				else
-					@browser.files.for-each (file) ~>
+					@browser.files.for-each (file) =>
 						file._selected = false
 					@file._selected = true
-					@browser.trigger \change-selection @file
+					@browser.trigger 'change-selection' @file
 
-		@oncontextmenu = (e) ~>
+		oncontextmenu(e) {
 			e.prevent-default!
 			e.stop-immediate-propagation!
 
-			@is-contextmenu-showing = true
-			@update!
-			ctx = document.body.append-child document.create-element \mk-drive-browser-file-contextmenu
+			this.is-contextmenu-showing = true
+			this.update();
+			ctx = document.body.appendChild document.createElement 'mk-drive-browser-file-contextmenu' 
 			ctx = riot.mount ctx, do
 				browser: @browser
 				file: @file
@@ -185,25 +185,25 @@
 			ctx.open do
 				x: e.page-x - window.page-x-offset
 				y: e.page-y - window.page-y-offset
-			ctx.on \closed ~>
-				@is-contextmenu-showing = false
-				@update!
+			ctx.on('closed', () => {
+				this.is-contextmenu-showing = false
+				this.update();
 			return false
 
-		@ondragstart = (e) ~>
-			e.data-transfer.effect-allowed = \move
+		ondragstart(e) {
+			e.data-transfer.effect-allowed = 'move' 
 			e.data-transfer.set-data 'text' JSON.stringify do
-				type: \file
+				type: 'file' 
 				id: @file.id
 				file: @file
-			@is-dragging = true
+			this.is-dragging = true
 
-			# 親ブラウザに対して、ドラッグが開始されたフラグを立てる
-			# (=あなたの子供が、ドラッグを開始しましたよ)
+			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
+			// (=あなたの子供が、ドラッグを開始しましたよ)
 			@browser.is-drag-source = true
 
-		@ondragend = (e) ~>
-			@is-dragging = false
+		ondragend(e) {
+			this.is-dragging = false
 			@browser.is-drag-source = false
 	</script>
 </mk-drive-browser-file>
diff --git a/src/web/app/desktop/tags/drive/folder-contextmenu.tag b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
index aea0904aa..20cb264e5 100644
--- a/src/web/app/desktop/tags/drive/folder-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
@@ -18,49 +18,49 @@
 		</ul>
 	</mk-contextmenu>
 	<script>
-		@mixin \api
-		@mixin \input-dialog
+		this.mixin('api');
+		this.mixin('input-dialog');
 
-		@browser = @opts.browser
-		@folder = @opts.folder
+		this.browser = this.opts.browser
+		this.folder = this.opts.folder
 
-		@open = (pos) ~>
-			@refs.ctx.open pos
+		open(pos) {
+			this.refs.ctx.open pos
 
-			@refs.ctx.on \closed ~>
-				@trigger \closed
-				@unmount!
+			this.refs.ctx.on('closed', () => {
+				this.trigger('closed');
+				this.unmount();
 
-		@move = ~>
+		move() {
 			@browser.move @folder.id
-			@refs.ctx.close!
+			this.refs.ctx.close!
 
-		@new-window = ~>
+		new-window() {
 			@browser.new-window @folder.id
-			@refs.ctx.close!
+			this.refs.ctx.close!
 
-		@create-folder = ~>
+		create-folder() {
 			@browser.create-folder!
-			@refs.ctx.close!
+			this.refs.ctx.close!
 
-		@upload = ~>
+		upload() {
 			@browser.select-lcoal-file!
-			@refs.ctx.close!
+			this.refs.ctx.close!
 
-		@rename = ~>
-			@refs.ctx.close!
+		rename() {
+			this.refs.ctx.close!
 
 			name <~ @input-dialog do
 				'フォルダ名の変更'
 				'新しいフォルダ名を入力してください'
 				@folder.name
 
-			@api \drive/folders/update do
+			this.api 'drive/folders/update' do
 				folder_id: @folder.id
 				name: name
-			.then ~>
-				# something
-			.catch (err) ~>
+			.then =>
+				// something
+			.catch (err) =>
 				console.error err
 	</script>
 </mk-drive-browser-folder-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/folder.tag b/src/web/app/desktop/tags/drive/folder.tag
index b6d52f19e..e14f70f41 100644
--- a/src/web/app/desktop/tags/drive/folder.tag
+++ b/src/web/app/desktop/tags/drive/folder.tag
@@ -50,124 +50,124 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \dialog
+		this.mixin('api');
+		this.mixin('dialog');
 
-		@folder = @opts.folder
-		@browser = @parent
+		this.folder = this.opts.folder
+		this.browser = this.parent
 
-		@title = @folder.name
-		@hover = false
-		@draghover = false
-		@is-contextmenu-showing = false
+		this.title = @folder.name
+		this.hover = false
+		this.draghover = false
+		this.is-contextmenu-showing = false
 
-		@onclick = ~>
+		onclick() {
 			@browser.move @folder
 
-		@onmouseover = ~>
-			@hover = true
+		onmouseover() {
+			this.hover = true
 
-		@onmouseout = ~>
-			@hover = false
+		onmouseout() {
+			this.hover = false
 
-		@ondragover = (e) ~>
+		ondragover(e) {
 			e.prevent-default!
 			e.stop-propagation!
 
-			# 自分自身がドラッグされていない場合
+			// 自分自身がドラッグされていない場合
 			if !@is-dragging
-				# ドラッグされてきたものがファイルだったら
-				if e.data-transfer.effect-allowed == \all
-					e.data-transfer.drop-effect = \copy
+				// ドラッグされてきたものがファイルだったら
+				if e.data-transfer.effect-allowed == 'all' 
+					e.data-transfer.drop-effect = 'copy' 
 				else
-					e.data-transfer.drop-effect = \move
+					e.data-transfer.drop-effect = 'move' 
 			else
-				# 自分自身にはドロップさせない
-				e.data-transfer.drop-effect = \none
+				// 自分自身にはドロップさせない
+				e.data-transfer.drop-effect = 'none' 
 			return false
 
-		@ondragenter = ~>
+		ondragenter() {
 			if !@is-dragging
-				@draghover = true
+				this.draghover = true
 
-		@ondragleave = ~>
-			@draghover = false
+		ondragleave() {
+			this.draghover = false
 
-		@ondrop = (e) ~>
+		ondrop(e) {
 			e.stop-propagation!
-			@draghover = false
+			this.draghover = false
 
-			# ファイルだったら
+			// ファイルだったら
 			if e.data-transfer.files.length > 0
-				Array.prototype.for-each.call e.data-transfer.files, (file) ~>
+				Array.prototype.for-each.call e.data-transfer.files, (file) =>
 					@browser.upload file, @folder
 				return false
 
-			# データ取得
+			// データ取得
 			data = e.data-transfer.get-data 'text'
 			if !data?
 				return false
 
-			# パース
+			// パース
 			obj = JSON.parse data
 
-			# (ドライブの)ファイルだったら
-			if obj.type == \file
+			// (ドライブの)ファイルだったら
+			if obj.type == 'file' 
 				file = obj.id
 				@browser.remove-file file
-				@api \drive/files/update do
+				this.api 'drive/files/update' do
 					file_id: file
 					folder_id: @folder.id
-				.then ~>
-					# something
-				.catch (err, text-status) ~>
+				.then =>
+					// something
+				.catch (err, text-status) =>
 					console.error err
 
-			# (ドライブの)フォルダーだったら
-			else if obj.type == \folder
+			// (ドライブの)フォルダーだったら
+			else if obj.type == 'folder' 
 				folder = obj.id
-				# 移動先が自分自身ならreject
+				// 移動先が自分自身ならreject
 				if folder == @folder.id
 					return false
 				@browser.remove-folder folder
-				@api \drive/folders/update do
+				this.api 'drive/folders/update' do
 					folder_id: folder
 					parent_id: @folder.id
-				.then ~>
-					# something
-				.catch (err) ~>
+				.then =>
+					// something
+				.catch (err) =>
 					if err == 'detected-circular-definition'
 						@dialog do
 							'<i class="fa fa-exclamation-triangle"></i>操作を完了できません'
 							'移動先のフォルダーは、移動するフォルダーのサブフォルダーです。'
 							[
-								text: \OK
+								text: 'OK' 
 							]
 
 			return false
 
-		@ondragstart = (e) ~>
-			e.data-transfer.effect-allowed = \move
+		ondragstart(e) {
+			e.data-transfer.effect-allowed = 'move' 
 			e.data-transfer.set-data 'text' JSON.stringify do
-				type: \folder
+				type: 'folder' 
 				id: @folder.id
-			@is-dragging = true
+			this.is-dragging = true
 
-			# 親ブラウザに対して、ドラッグが開始されたフラグを立てる
-			# (=あなたの子供が、ドラッグを開始しましたよ)
+			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
+			// (=あなたの子供が、ドラッグを開始しましたよ)
 			@browser.is-drag-source = true
 
-		@ondragend = (e) ~>
-			@is-dragging = false
+		ondragend(e) {
+			this.is-dragging = false
 			@browser.is-drag-source = false
 
-		@oncontextmenu = (e) ~>
+		oncontextmenu(e) {
 			e.prevent-default!
 			e.stop-immediate-propagation!
 
-			@is-contextmenu-showing = true
-			@update!
-			ctx = document.body.append-child document.create-element \mk-drive-browser-folder-contextmenu
+			this.is-contextmenu-showing = true
+			this.update();
+			ctx = document.body.appendChild document.createElement 'mk-drive-browser-folder-contextmenu' 
 			ctx = riot.mount ctx, do
 				browser: @browser
 				folder: @folder
@@ -175,9 +175,9 @@
 			ctx.open do
 				x: e.page-x - window.page-x-offset
 				y: e.page-y - window.page-y-offset
-			ctx.on \closed ~>
-				@is-contextmenu-showing = false
-				@update!
+			ctx.on('closed', () => {
+				this.is-contextmenu-showing = false
+				this.update();
 
 			return false
 	</script>
diff --git a/src/web/app/desktop/tags/drive/nav-folder.tag b/src/web/app/desktop/tags/drive/nav-folder.tag
index 632783d20..afa628775 100644
--- a/src/web/app/desktop/tags/drive/nav-folder.tag
+++ b/src/web/app/desktop/tags/drive/nav-folder.tag
@@ -6,90 +6,90 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		# Riotのバグでnullを渡しても""になる
-		# https://github.com/riot/riot/issues/2080
-		#@folder = @opts.folder
-		@folder = if @opts.folder? and @opts.folder != '' then @opts.folder else null
-		@browser = @parent
+		// Riotのバグでnullを渡しても""になる
+		// https://github.com/riot/riot/issues/2080
+		#this.folder = this.opts.folder
+		this.folder = if this.opts.folder? and this.opts.folder != '' then this.opts.folder else null
+		this.browser = this.parent
 
-		@hover = false
+		this.hover = false
 
-		@onclick = ~>
+		onclick() {
 			@browser.move @folder
 
-		@onmouseover = ~>
-			@hover = true
+		onmouseover() {
+			this.hover = true
 
-		@onmouseout = ~>
-			@hover = false
+		onmouseout() {
+			this.hover = false
 
-		@ondragover = (e) ~>
+		ondragover(e) {
 			e.prevent-default!
 			e.stop-propagation!
 
-			# このフォルダがルートかつカレントディレクトリならドロップ禁止
+			// このフォルダがルートかつカレントディレクトリならドロップ禁止
 			if @folder == null and @browser.folder == null
-				e.data-transfer.drop-effect = \none
-			# ドラッグされてきたものがファイルだったら
-			else if e.data-transfer.effect-allowed == \all
-				e.data-transfer.drop-effect = \copy
+				e.data-transfer.drop-effect = 'none' 
+			// ドラッグされてきたものがファイルだったら
+			else if e.data-transfer.effect-allowed == 'all' 
+				e.data-transfer.drop-effect = 'copy' 
 			else
-				e.data-transfer.drop-effect = \move
+				e.data-transfer.drop-effect = 'move' 
 			return false
 
-		@ondragenter = ~>
+		ondragenter() {
 			if @folder != null or @browser.folder != null
-				@draghover = true
+				this.draghover = true
 
-		@ondragleave = ~>
+		ondragleave() {
 			if @folder != null or @browser.folder != null
-				@draghover = false
+				this.draghover = false
 
-		@ondrop = (e) ~>
+		ondrop(e) {
 			e.stop-propagation!
-			@draghover = false
+			this.draghover = false
 
-			# ファイルだったら
+			// ファイルだったら
 			if e.data-transfer.files.length > 0
-				Array.prototype.for-each.call e.data-transfer.files, (file) ~>
+				Array.prototype.for-each.call e.data-transfer.files, (file) =>
 					@browser.upload file, @folder
 				return false
 
-			# データ取得
+			// データ取得
 			data = e.data-transfer.get-data 'text'
 			if !data?
 				return false
 
-			# パース
+			// パース
 			obj = JSON.parse data
 
-			# (ドライブの)ファイルだったら
-			if obj.type == \file
+			// (ドライブの)ファイルだったら
+			if obj.type == 'file' 
 				file = obj.id
 				@browser.remove-file file
-				@api \drive/files/update do
+				this.api 'drive/files/update' do
 					file_id: file
 					folder_id: if @folder? then @folder.id else null
-				.then ~>
-					# something
-				.catch (err, text-status) ~>
+				.then =>
+					// something
+				.catch (err, text-status) =>
 					console.error err
 
-			# (ドライブの)フォルダーだったら
-			else if obj.type == \folder
+			// (ドライブの)フォルダーだったら
+			else if obj.type == 'folder' 
 				folder = obj.id
-				# 移動先が自分自身ならreject
+				// 移動先が自分自身ならreject
 				if @folder? and folder == @folder.id
 					return false
 				@browser.remove-folder folder
-				@api \drive/folders/update do
+				this.api 'drive/folders/update' do
 					folder_id: folder
 					parent_id: if @folder? then @folder.id else null
-				.then ~>
-					# something
-				.catch (err, text-status) ~>
+				.then =>
+					// something
+				.catch (err, text-status) =>
 					console.error err
 
 			return false
diff --git a/src/web/app/desktop/tags/follow-button.tag b/src/web/app/desktop/tags/follow-button.tag
index 1e82b5ed1..575c99c70 100644
--- a/src/web/app/desktop/tags/follow-button.tag
+++ b/src/web/app/desktop/tags/follow-button.tag
@@ -67,58 +67,58 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
-		@mixin \stream
+		this.mixin('api');
+		this.mixin('is-promise');
+		this.mixin('stream');
 
-		@user = null
-		@user-promise = if @is-promise @opts.user then @opts.user else Promise.resolve @opts.user
-		@init = true
-		@wait = false
+		this.user = null
+		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
+		this.init = true
+		this.wait = false
 
-		@on \mount ~>
-			@user-promise.then (user) ~>
-				@user = user
-				@init = false
-				@update!
-				@stream.on \follow @on-stream-follow
-				@stream.on \unfollow @on-stream-unfollow
+		this.on('mount', () => {
+			@user-promise.then (user) =>
+				this.user = user
+				this.init = false
+				this.update();
+				@stream.on 'follow' this.on-stream-follow
+				@stream.on 'unfollow' this.on-stream-unfollow
 
-		@on \unmount ~>
-			@stream.off \follow @on-stream-follow
-			@stream.off \unfollow @on-stream-unfollow
+		this.on('unmount', () => {
+			@stream.off 'follow' this.on-stream-follow
+			@stream.off 'unfollow' this.on-stream-unfollow
 
-		@on-stream-follow = (user) ~>
+		on-stream-follow(user) {
 			if user.id == @user.id
-				@user = user
-				@update!
+				this.user = user
+				this.update();
 
-		@on-stream-unfollow = (user) ~>
+		on-stream-unfollow(user) {
 			if user.id == @user.id
-				@user = user
-				@update!
+				this.user = user
+				this.update();
 
-		@onclick = ~>
-			@wait = true
+		onclick() {
+			this.wait = true
 			if @user.is_following
-				@api \following/delete do
+				this.api 'following/delete' do
 					user_id: @user.id
-				.then ~>
+				.then =>
 					@user.is_following = false
 				.catch (err) ->
 					console.error err
-				.then ~>
-					@wait = false
-					@update!
+				.then =>
+					this.wait = false
+					this.update();
 			else
-				@api \following/create do
+				this.api 'following/create' do
 					user_id: @user.id
-				.then ~>
+				.then =>
 					@user.is_following = true
 				.catch (err) ->
 					console.error err
-				.then ~>
-					@wait = false
-					@update!
+				.then =>
+					this.wait = false
+					this.update();
 	</script>
 </mk-follow-button>
diff --git a/src/web/app/desktop/tags/following-setuper.tag b/src/web/app/desktop/tags/following-setuper.tag
index 1b2e5aafa..5faba3e65 100644
--- a/src/web/app/desktop/tags/following-setuper.tag
+++ b/src/web/app/desktop/tags/following-setuper.tag
@@ -123,41 +123,41 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \user-preview
+		this.mixin('api');
+		this.mixin('user-preview');
 
-		@users = null
-		@loading = true
+		this.users = null
+		this.loading = true
 
-		@limit = 6users
-		@page = 0
+		this.limit = 6users
+		this.page = 0
 
-		@on \mount ~>
+		this.on('mount', () => {
 			@load!
 
-		@load = ~>
-			@loading = true
-			@users = null
-			@update!
+		load() {
+			this.loading = true
+			this.users = null
+			this.update();
 
-			@api \users/recommendation do
+			this.api 'users/recommendation' do
 				limit: @limit
 				offset: @limit * @page
-			.then (users) ~>
-				@loading = false
-				@users = users
-				@update!
+			.then (users) =>
+				this.loading = false
+				this.users = users
+				this.update();
 			.catch (err, text-status) ->
 				console.error err
 
-		@refresh = ~>
+		refresh() {
 			if @users.length < @limit
-				@page = 0
+				this.page = 0
 			else
 				@page++
 			@load!
 
-		@close = ~>
-			@unmount!
+		close() {
+			this.unmount();
 	</script>
 </mk-following-setuper>
diff --git a/src/web/app/desktop/tags/go-top.tag b/src/web/app/desktop/tags/go-top.tag
index d43e68ea9..42efaf2f2 100644
--- a/src/web/app/desktop/tags/go-top.tag
+++ b/src/web/app/desktop/tags/go-top.tag
@@ -1,14 +1,14 @@
 <mk-go-top>
 	<button class="hidden" title="一番上へ"><i class="fa fa-angle-up"></i></button>
 	<script>
-		window.add-event-listener \load @on-scroll
-		window.add-event-listener \scroll @on-scroll
-		window.add-event-listener \resize @on-scroll
+		window.add-event-listener 'load' this.on-scroll
+		window.add-event-listener 'scroll' this.on-scroll
+		window.add-event-listener 'resize' this.on-scroll
 
-		@on-scroll = ~>
+		on-scroll() {
 			if $ window .scroll-top! > 500px
-				@remove-class \hidden
+				@remove-class 'hidden' 
 			else
-				@add-class \hidden
+				@add-class 'hidden' 
 	</script>
 </mk-go-top>
diff --git a/src/web/app/desktop/tags/home-widgets/calendar.tag b/src/web/app/desktop/tags/home-widgets/calendar.tag
index 3d62dc60c..81378b8a7 100644
--- a/src/web/app/desktop/tags/home-widgets/calendar.tag
+++ b/src/web/app/desktop/tags/home-widgets/calendar.tag
@@ -106,43 +106,43 @@
 
 	</style>
 	<script>
-		@draw = ~>
+		draw() {
 			now = new Date!
 			nd = now.get-date!
 			nm = now.get-month!
 			ny = now.get-full-year!
 
-			@year = ny
-			@month = nm + 1
-			@day = nd
-			@week-day = [\日 \月 \火 \水 \木 \金 \土][now.get-day!]
+			this.year = ny
+			this.month = nm + 1
+			this.day = nd
+			this.week-day = [\日 '月' \火 '水' \木 '金' \土][now.get-day!]
 
 			@day-numer   = (now - (new Date ny, nm, nd))
 			@day-denom   = 1000ms * 60s * 60m * 24h
-			@month-numer = (now - (new Date ny, nm, 1))
-			@month-denom = (new Date ny, nm + 1,  1) - (new Date ny, nm, 1)
+			this.month-numer = (now - (new Date ny, nm, 1))
+			this.month-denom = (new Date ny, nm + 1,  1) - (new Date ny, nm, 1)
 			@year-numer  = (now - (new Date ny, 0, 1))
 			@year-denom  = (new Date ny + 1, 0,  1) - (new Date ny, 0, 1)
 
 			@day-p   = @day-numer   / @day-denom   * 100
-			@month-p = @month-numer / @month-denom * 100
+			this.month-p = @month-numer / @month-denom * 100
 			@year-p  = @year-numer  / @year-denom  * 100
 
-			@is-holiday =
+			this.is-holiday = 
 				(now.get-day! == 0 or now.get-day! == 6)
 
-			@special =
-				| nm == 0 and nd == 1 => \on-new-years-day
+			this.special = 
+				| nm == 0 and nd == 1 => 'on-new-years-day' 
 				| _ => false
 
-			@update!
+			this.update();
 
 		@draw!
 
-		@on \mount ~>
-			@clock = set-interval @draw, 1000ms
+		this.on('mount', () => {
+			this.clock = set-interval @draw, 1000ms
 
-		@on \unmount ~>
+		this.on('unmount', () => {
 			clear-interval @clock
 	</script>
 </mk-calendar-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/donation.tag b/src/web/app/desktop/tags/home-widgets/donation.tag
index 047ea5011..57c86a875 100644
--- a/src/web/app/desktop/tags/home-widgets/donation.tag
+++ b/src/web/app/desktop/tags/home-widgets/donation.tag
@@ -32,5 +32,5 @@
 					color #999
 
 	</style>
-	<script>@mixin \user-preview</script>
+	<script>this.mixin('user-preview');</script>
 </mk-donation-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/mentions.tag b/src/web/app/desktop/tags/home-widgets/mentions.tag
index d683b0817..149a30238 100644
--- a/src/web/app/desktop/tags/home-widgets/mentions.tag
+++ b/src/web/app/desktop/tags/home-widgets/mentions.tag
@@ -46,65 +46,65 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \api
+		this.mixin('i');
+		this.mixin('api');
 
-		@is-loading = true
-		@is-empty = false
-		@more-loading = false
-		@mode = \all
+		this.is-loading = true
+		this.is-empty = false
+		this.more-loading = false
+		this.mode = 'all' 
 
-		@on \mount ~>
-			document.add-event-listener \keydown @on-document-keydown
-			window.add-event-listener \scroll @on-scroll
+		this.on('mount', () => {
+			document.add-event-listener 'keydown' this.on-document-keydown
+			window.add-event-listener 'scroll' this.on-scroll
 
-			@fetch ~>
-				@trigger \loaded
+			@fetch =>
+				this.trigger('loaded');
 
-		@on \unmount ~>
-			document.remove-event-listener \keydown @on-document-keydown
-			window.remove-event-listener \scroll @on-scroll
+		this.on('unmount', () => {
+			document.remove-event-listener 'keydown' this.on-document-keydown
+			window.remove-event-listener 'scroll' this.on-scroll
 
-		@on-document-keydown = (e) ~>
+		on-document-keydown(e) {
 			tag = e.target.tag-name.to-lower-case!
-			if tag != \input and tag != \textarea
-				if e.which == 84 # t
-					@refs.timeline.focus!
+			if tag != 'input' and tag != 'textarea' 
+				if e.which == 84 // t
+					this.refs.timeline.focus();
 
-		@fetch = (cb) ~>
-			@api \posts/mentions do
-				following: @mode == \following
-			.then (posts) ~>
-				@is-loading = false
-				@is-empty = posts.length == 0
-				@update!
-				@refs.timeline.set-posts posts
+		fetch(cb) {
+			this.api 'posts/mentions' do
+				following: @mode == 'following' 
+			.then (posts) =>
+				this.is-loading = false
+				this.is-empty = posts.length == 0
+				this.update();
+				this.refs.timeline.set-posts posts
 				if cb? then cb!
-			.catch (err) ~>
+			.catch (err) =>
 				console.error err
 				if cb? then cb!
 
-		@more = ~>
-			if @more-loading or @is-loading or @refs.timeline.posts.length == 0
+		more() {
+			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
 				return
-			@more-loading = true
-			@update!
-			@api \posts/mentions do
-				following: @mode == \following
-				max_id: @refs.timeline.tail!.id
-			.then (posts) ~>
-				@more-loading = false
-				@update!
-				@refs.timeline.prepend-posts posts
-			.catch (err) ~>
+			this.more-loading = true
+			this.update();
+			this.api 'posts/mentions' do
+				following: @mode == 'following' 
+				max_id: this.refs.timeline.tail!.id
+			.then (posts) =>
+				this.more-loading = false
+				this.update();
+				this.refs.timeline.prepend-posts posts
+			.catch (err) =>
 				console.error err
 
-		@on-scroll = ~>
+		on-scroll() {
 			current = window.scroll-y + window.inner-height
 			if current > document.body.offset-height - 8
 				@more!
 
-		@set-mode = (mode) ~>
+		set-mode(mode) {
 			@update do
 				mode: mode
 			@fetch!
diff --git a/src/web/app/desktop/tags/home-widgets/notifications.tag b/src/web/app/desktop/tags/home-widgets/notifications.tag
index b09ae976e..4ed7f6378 100644
--- a/src/web/app/desktop/tags/home-widgets/notifications.tag
+++ b/src/web/app/desktop/tags/home-widgets/notifications.tag
@@ -43,8 +43,8 @@
 
 	</style>
 	<script>
-		@settings = ~>
-			w = riot.mount document.body.append-child document.create-element \mk-settings-window .0
-			w.switch \notification
+		settings() {
+			w = riot.mount document.body.appendChild document.createElement 'mk-settings-window' .0
+			w.switch 'notification' 
 	</script>
 </mk-notifications-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/photo-stream.tag b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
index 6ce0fd33f..9b7756108 100644
--- a/src/web/app/desktop/tags/home-widgets/photo-stream.tag
+++ b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
@@ -57,31 +57,31 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \stream
+		this.mixin('api');
+		this.mixin('stream');
 
-		@images = []
-		@initializing = true
+		this.images = []
+		this.initializing = true
 
-		@on \mount ~>
-			@stream.on \drive_file_created @on-stream-drive-file-created
+		this.on('mount', () => {
+			@stream.on 'drive_file_created' this.on-stream-drive-file-created
 
-			@api \drive/stream do
+			this.api 'drive/stream' do
 				type: 'image/*'
 				limit: 9images
-			.then (images) ~>
-				@initializing = false
-				@images = images
-				@update!
+			.then (images) =>
+				this.initializing = false
+				this.images = images
+				this.update();
 
-		@on \unmount ~>
-			@stream.off \drive_file_created @on-stream-drive-file-created
+		this.on('unmount', () => {
+			@stream.off 'drive_file_created' this.on-stream-drive-file-created
 
-		@on-stream-drive-file-created = (file) ~>
+		on-stream-drive-file-created(file) {
 			if /^image\/.+$/.test file.type
 				@images.unshift file
 				if @images.length > 9
 					@images.pop!
-				@update!
+				this.update();
 	</script>
 </mk-photo-stream-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/profile.tag b/src/web/app/desktop/tags/home-widgets/profile.tag
index 9f11072b7..d8d1f6107 100644
--- a/src/web/app/desktop/tags/home-widgets/profile.tag
+++ b/src/web/app/desktop/tags/home-widgets/profile.tag
@@ -41,15 +41,15 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \user-preview
-		@mixin \update-avatar
-		@mixin \update-banner
+		this.mixin('i');
+		this.mixin('user-preview');
+		this.mixin('update-avatar');
+		this.mixin('update-banner');
 
-		@set-avatar = ~>
+		set-avatar() {
 			@update-avatar @I
 
-		@set-banner = ~>
+		set-banner() {
 			@update-banner @I
 	</script>
 </mk-profile-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/rss-reader.tag b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
index 0efd5cbec..6778ea3bb 100644
--- a/src/web/app/desktop/tags/home-widgets/rss-reader.tag
+++ b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
@@ -64,31 +64,31 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \NotImplementedException
+		this.mixin('api');
+		this.mixin('NotImplementedException');
 
-		@url = 'http://news.yahoo.co.jp/pickup/rss.xml'
-		@items = []
-		@initializing = true
+		this.url = 'http://news.yahoo.co.jp/pickup/rss.xml'
+		this.items = []
+		this.initializing = true
 
-		@on \mount ~>
+		this.on('mount', () => {
 			@fetch!
-			@clock = set-interval @fetch, 60000ms
+			this.clock = set-interval @fetch, 60000ms
 
-		@on \unmount ~>
+		this.on('unmount', () => {
 			clear-interval @clock
 
-		@fetch = ~>
-			@api CONFIG.url + '/api:rss' do
+		fetch() {
+			this.api CONFIG.url + '/api:rss' do
 				url: @url
-			.then (feed) ~>
-				@items = feed.rss.channel.item
-				@initializing = false
-				@update!
+			.then (feed) =>
+				this.items = feed.rss.channel.item
+				this.initializing = false
+				this.update();
 			.catch (err) ->
 				console.error err
 
-		@settings = ~>
+		settings() {
 			@NotImplementedException!
 	</script>
 </mk-rss-reader-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index 9f5bb3890..10918b5e0 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -32,78 +32,78 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \api
-		@mixin \stream
+		this.mixin('i');
+		this.mixin('api');
+		this.mixin('stream');
 
-		@is-loading = true
-		@is-empty = false
-		@more-loading = false
-		@no-following = @I.following_count == 0
+		this.is-loading = true
+		this.is-empty = false
+		this.more-loading = false
+		this.no-following = @I.following_count == 0
 
-		@on \mount ~>
-			@stream.on \post @on-stream-post
-			@stream.on \follow @on-stream-follow
-			@stream.on \unfollow @on-stream-unfollow
+		this.on('mount', () => {
+			@stream.on 'post' this.on-stream-post
+			@stream.on 'follow' this.on-stream-follow
+			@stream.on 'unfollow' this.on-stream-unfollow
 
-			document.add-event-listener \keydown @on-document-keydown
-			window.add-event-listener \scroll @on-scroll
+			document.add-event-listener 'keydown' this.on-document-keydown
+			window.add-event-listener 'scroll' this.on-scroll
 
-			@load ~>
-				@trigger \loaded
+			@load =>
+				this.trigger('loaded');
 
-		@on \unmount ~>
-			@stream.off \post @on-stream-post
-			@stream.off \follow @on-stream-follow
-			@stream.off \unfollow @on-stream-unfollow
+		this.on('unmount', () => {
+			@stream.off 'post' this.on-stream-post
+			@stream.off 'follow' this.on-stream-follow
+			@stream.off 'unfollow' this.on-stream-unfollow
 
-			document.remove-event-listener \keydown @on-document-keydown
-			window.remove-event-listener \scroll @on-scroll
+			document.remove-event-listener 'keydown' this.on-document-keydown
+			window.remove-event-listener 'scroll' this.on-scroll
 
-		@on-document-keydown = (e) ~>
+		on-document-keydown(e) {
 			tag = e.target.tag-name.to-lower-case!
-			if tag != \input and tag != \textarea
-				if e.which == 84 # t
-					@refs.timeline.focus!
+			if tag != 'input' and tag != 'textarea' 
+				if e.which == 84 // t
+					this.refs.timeline.focus();
 
-		@load = (cb) ~>
-			@api \posts/timeline
-			.then (posts) ~>
-				@is-loading = false
-				@is-empty = posts.length == 0
-				@update!
-				@refs.timeline.set-posts posts
+		load(cb) {
+			this.api 'posts/timeline' 
+			.then (posts) =>
+				this.is-loading = false
+				this.is-empty = posts.length == 0
+				this.update();
+				this.refs.timeline.set-posts posts
 				if cb? then cb!
-			.catch (err) ~>
+			.catch (err) =>
 				console.error err
 				if cb? then cb!
 
-		@more = ~>
-			if @more-loading or @is-loading or @refs.timeline.posts.length == 0
+		more() {
+			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
 				return
-			@more-loading = true
-			@update!
-			@api \posts/timeline do
-				max_id: @refs.timeline.tail!.id
-			.then (posts) ~>
-				@more-loading = false
-				@update!
-				@refs.timeline.prepend-posts posts
-			.catch (err) ~>
+			this.more-loading = true
+			this.update();
+			this.api 'posts/timeline' do
+				max_id: this.refs.timeline.tail!.id
+			.then (posts) =>
+				this.more-loading = false
+				this.update();
+				this.refs.timeline.prepend-posts posts
+			.catch (err) =>
 				console.error err
 
-		@on-stream-post = (post) ~>
-			@is-empty = false
-			@update!
-			@refs.timeline.add-post post
+		on-stream-post(post) {
+			this.is-empty = false
+			this.update();
+			this.refs.timeline.add-post post
 
-		@on-stream-follow = ~>
+		on-stream-follow() {
 			@load!
 
-		@on-stream-unfollow = ~>
+		on-stream-unfollow() {
 			@load!
 
-		@on-scroll = ~>
+		on-scroll() {
 			current = window.scroll-y + window.inner-height
 			if current > document.body.offset-height - 8
 				@more!
diff --git a/src/web/app/desktop/tags/home-widgets/tips.tag b/src/web/app/desktop/tags/home-widgets/tips.tag
index 2552c266d..c28514bbf 100644
--- a/src/web/app/desktop/tags/home-widgets/tips.tag
+++ b/src/web/app/desktop/tags/home-widgets/tips.tag
@@ -29,7 +29,7 @@
 
 	</style>
 	<script>
-		@tips = [
+		this.tips = [
 			'<kbd>t</kbd>でタイムラインにフォーカスできます'
 			'<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます'
 			'投稿フォームにはファイルをドラッグ&ドロップできます'
@@ -41,31 +41,31 @@
 			'MisskeyはMIT Licenseです'
 		]
 
-		@on \mount ~>
+		this.on('mount', () => {
 			@set!
-			@clock = set-interval @change, 20000ms
+			this.clock = set-interval @change, 20000ms
 
-		@on \unmount ~>
+		this.on('unmount', () => {
 			clear-interval @clock
 
-		@set = ~>
-			@refs.text.innerHTML = @tips[Math.floor Math.random! * @tips.length]
-			@update!
+		set() {
+			this.refs.text.innerHTML = @tips[Math.floor Math.random! * @tips.length]
+			this.update();
 
-		@change = ~>
-			Velocity @refs.tip, {
+		change() {
+			Velocity this.refs.tip, {
 				opacity: 0
 			} {
 				duration: 500ms
-				easing: \linear
+				easing: 'linear' 
 				complete: @set
 			}
 
-			Velocity @refs.tip, {
+			Velocity this.refs.tip, {
 				opacity: 1
 			} {
 				duration: 500ms
-				easing: \linear
+				easing: 'linear' 
 			}
 	</script>
 </mk-tips-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
index 8e94090dc..b2ec4ba88 100644
--- a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
+++ b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
@@ -109,42 +109,42 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \user-preview
+		this.mixin('api');
+		this.mixin('user-preview');
 
-		@users = null
-		@loading = true
+		this.users = null
+		this.loading = true
 
-		@limit = 3users
-		@page = 0
+		this.limit = 3users
+		this.page = 0
 
-		@on \mount ~>
+		this.on('mount', () => {
 			@fetch!
-			@clock = set-interval ~>
+			this.clock = set-interval =>
 				if @users.length < @limit
 					@fetch true
 			, 60000ms
 
-		@on \unmount ~>
+		this.on('unmount', () => {
 			clear-interval @clock
 
-		@fetch = (quiet = false) ~>
-			@loading = true
-			@users = null
-			if not quiet then @update!
-			@api \users/recommendation do
+		fetch(quiet = false) {
+			this.loading = true
+			this.users = null
+			if not quiet then this.update();
+			this.api 'users/recommendation' do
 				limit: @limit
 				offset: @limit * @page
-			.then (users) ~>
-				@loading = false
-				@users = users
-				@update!
+			.then (users) =>
+				this.loading = false
+				this.users = users
+				this.update();
 			.catch (err, text-status) ->
 				console.error err
 
-		@refresh = ~>
+		refresh() {
 			if @users.length < @limit
-				@page = 0
+				this.page = 0
 			else
 				@page++
 			@fetch!
diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag
index b2ba4e280..182f557b7 100644
--- a/src/web/app/desktop/tags/home.tag
+++ b/src/web/app/desktop/tags/home.tag
@@ -58,33 +58,33 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mode = @opts.mode || \timeline
+		this.mixin('i');
+		this.mode = this.opts.mode || 'timeline' 
 
-		# https://github.com/riot/riot/issues/2080
-		if @mode == '' then @mode = \timeline
+		// https://github.com/riot/riot/issues/2080
+		if @mode == '' then this.mode = 'timeline' 
 
-		@home = []
+		this.home = []
 
-		@on \mount ~>
-			@refs.tl.on \loaded ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			this.refs.tl.on('loaded', () => {
+				this.trigger('loaded');
 
-			@I.data.home.for-each (widget) ~>
+			@I.data.home.for-each (widget) =>
 				try
-					el = document.create-element \mk- + widget.name + \-home-widget
+					el = document.createElement 'mk-' + widget.name + '-home-widget' 
 					switch widget.place
-						| \left => @refs.left.append-child el
-						| \right => @refs.right.append-child el
+						| 'left' => this.refs.left.appendChild el
+						| 'right' => this.refs.right.appendChild el
 					@home.push (riot.mount el, do
 						id: widget.id
 						data: widget.data
 					.0)
 				catch e
-					# noop
+					// noop
 
-		@on \unmount ~>
-			@home.for-each (widget) ~>
+		this.on('unmount', () => {
+			@home.for-each (widget) =>
 				widget.unmount!
 	</script>
 </mk-home>
diff --git a/src/web/app/desktop/tags/image-dialog.tag b/src/web/app/desktop/tags/image-dialog.tag
index d7660bb95..ae42a968b 100644
--- a/src/web/app/desktop/tags/image-dialog.tag
+++ b/src/web/app/desktop/tags/image-dialog.tag
@@ -35,41 +35,41 @@
 
 	</style>
 	<script>
-		@image = @opts.image
+		this.image = this.opts.image
 
-		@on \mount ~>
-			Velocity @root, {
+		this.on('mount', () => {
+			Velocity this.root, {
 				opacity: 1
 			} {
 				duration: 100ms
-				easing: \linear
+				easing: 'linear' 
 			}
 
 			#Velocity @img, {
-			#	scale: 1
-			#	opacity: 1
+			// scale: 1
+			// opacity: 1
 			#} {
-			#	duration: 200ms
-			#	easing: \ease-out
+			// duration: 200ms
+			// easing: 'ease-out' 
 			#}
 
-		@close = ~>
-			Velocity @root, {
+		close() {
+			Velocity this.root, {
 				opacity: 0
 			} {
 				duration: 100ms
-				easing: \linear
-				complete: ~> @unmount!
+				easing: 'linear' 
+				complete: => this.unmount();
 			}
 
 			#Velocity @img, {
-			#	scale: 0.9
-			#	opacity: 0
+			// scale: 0.9
+			// opacity: 0
 			#} {
-			#	duration: 200ms
-			#	easing: \ease-in
-			#	complete: ~>
-			#		@unmount!
+			// duration: 200ms
+			// easing: 'ease-in' 
+			// complete: =>
+			// 	this.unmount();
 			#}
 	</script>
 </mk-image-dialog>
diff --git a/src/web/app/desktop/tags/images-viewer.tag b/src/web/app/desktop/tags/images-viewer.tag
index 017395e7b..7d552bc9f 100644
--- a/src/web/app/desktop/tags/images-viewer.tag
+++ b/src/web/app/desktop/tags/images-viewer.tag
@@ -26,19 +26,19 @@
 
 	</style>
 	<script>
-		@images = @opts.images
-		@image = @images.0
+		this.images = this.opts.images
+		this.image = @images.0
 
-		@mousemove = (e) ~>
-			rect = @refs.view.get-bounding-client-rect!
+		mousemove(e) {
+			rect = this.refs.view.get-bounding-client-rect!
 			mouse-x = e.client-x - rect.left
 			mouse-y = e.client-y - rect.top
-			xp = mouse-x / @refs.view.offset-width * 100
-			yp = mouse-y / @refs.view.offset-height * 100
-			@refs.view.style.background-position = xp + '% ' + yp + '%'
+			xp = mouse-x / this.refs.view.offset-width * 100
+			yp = mouse-y / this.refs.view.offset-height * 100
+			this.refs.view.style.background-position = xp + '% ' + yp + '%'
 
-		@click = ~>
-			dialog = document.body.append-child document.create-element \mk-image-dialog
+		click() {
+			dialog = document.body.appendChild document.createElement 'mk-image-dialog' 
 			riot.mount dialog, do
 				image: @image
 	</script>
diff --git a/src/web/app/desktop/tags/input-dialog.tag b/src/web/app/desktop/tags/input-dialog.tag
index d9f4ae3f4..a7dfdb807 100644
--- a/src/web/app/desktop/tags/input-dialog.tag
+++ b/src/web/app/desktop/tags/input-dialog.tag
@@ -116,40 +116,40 @@
 
 	</style>
 	<script>
-		@done = false
+		this.done = false
 
-		@title = @opts.title
-		@placeholder = @opts.placeholder
-		@default = @opts.default
-		@allow-empty = if @opts.allow-empty? then @opts.allow-empty else true
+		this.title = this.opts.title
+		this.placeholder = this.opts.placeholder
+		this.default = this.opts.default
+		this.allow-empty = if this.opts.allow-empty? then this.opts.allow-empty else true
 
-		@on \mount ~>
-			@text = @refs.window.refs.text
+		this.on('mount', () => {
+			this.text = this.refs.window.refs.text
 			if @default?
 				@text.value = @default
-			@text.focus!
+			@text.focus();
 
-			@refs.window.on \closing ~>
+			this.refs.window.on('closing', () => {
 				if @done
-					@opts.on-ok @text.value
+					this.opts.on-ok @text.value
 				else
-					if @opts.on-cancel?
-						@opts.on-cancel!
+					if this.opts.on-cancel?
+						this.opts.on-cancel!
 
-			@refs.window.on \closed ~>
-				@unmount!
+			this.refs.window.on('closed', () => {
+				this.unmount();
 
-		@cancel = ~>
-			@done = false
-			@refs.window.close!
+		cancel() {
+			this.done = false
+			this.refs.window.close!
 
-		@ok = ~>
+		ok() {
 			if not @allow-empty and @text.value == '' then return
-			@done = true
-			@refs.window.close!
+			this.done = true
+			this.refs.window.close!
 
-		@on-keydown = (e) ~>
-			if e.which == 13 # Enter
+		on-keydown(e) {
+			if e.which == 13 // Enter
 				e.prevent-default!
 				e.stop-propagation!
 				@ok!
diff --git a/src/web/app/desktop/tags/list-user.tag b/src/web/app/desktop/tags/list-user.tag
index 03dda494a..133efd2d1 100644
--- a/src/web/app/desktop/tags/list-user.tag
+++ b/src/web/app/desktop/tags/list-user.tag
@@ -93,5 +93,5 @@
 				right 16px
 
 	</style>
-	<script>@user = @opts.user</script>
+	<script>this.user = this.opts.user</script>
 </mk-list-user>
diff --git a/src/web/app/desktop/tags/messaging/room-window.tag b/src/web/app/desktop/tags/messaging/room-window.tag
index a7eddb591..3cf10ffe1 100644
--- a/src/web/app/desktop/tags/messaging/room-window.tag
+++ b/src/web/app/desktop/tags/messaging/room-window.tag
@@ -19,10 +19,10 @@
 
 	</style>
 	<script>
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@on \mount ~>
-			@refs.window.on \closed ~>
-				@unmount!
+		this.on('mount', () => {
+			this.refs.window.on('closed', () => {
+				this.unmount();
 	</script>
 </mk-messaging-room-window>
diff --git a/src/web/app/desktop/tags/messaging/window.tag b/src/web/app/desktop/tags/messaging/window.tag
index f81fd6681..2d9a060d6 100644
--- a/src/web/app/desktop/tags/messaging/window.tag
+++ b/src/web/app/desktop/tags/messaging/window.tag
@@ -19,12 +19,12 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			@refs.window.on \closed ~>
-				@unmount!
+		this.on('mount', () => {
+			this.refs.window.on('closed', () => {
+				this.unmount();
 
-			@refs.window.refs.index.on \navigate-user (user) ~>
-				w = document.body.append-child document.create-element \mk-messaging-room-window
+			this.refs.window.refs.index.on('navigate-user', user => {
+				w = document.body.appendChild document.createElement 'mk-messaging-room-window' 
 				riot.mount w, do
 					user: user
 	</script>
diff --git a/src/web/app/desktop/tags/notifications.tag b/src/web/app/desktop/tags/notifications.tag
index 58851786b..7ef13ad7e 100644
--- a/src/web/app/desktop/tags/notifications.tag
+++ b/src/web/app/desktop/tags/notifications.tag
@@ -177,34 +177,34 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \stream
-		@mixin \user-preview
-		@mixin \get-post-summary
+		this.mixin('api');
+		this.mixin('stream');
+		this.mixin('user-preview');
+		this.mixin('get-post-summary');
 
-		@notifications = []
-		@loading = true
+		this.notifications = []
+		this.loading = true
 
-		@on \mount ~>
-			@api \i/notifications
-			.then (notifications) ~>
-				@notifications = notifications
-				@loading = false
-				@update!
+		this.on('mount', () => {
+			this.api 'i/notifications' 
+			.then (notifications) =>
+				this.notifications = notifications
+				this.loading = false
+				this.update();
 			.catch (err, text-status) ->
 				console.error err
 
-			@stream.on \notification @on-notification
+			@stream.on 'notification' this.on-notification
 
-		@on \unmount ~>
-			@stream.off \notification @on-notification
+		this.on('unmount', () => {
+			@stream.off 'notification' this.on-notification
 
-		@on-notification = (notification) ~>
+		on-notification(notification) {
 			@notifications.unshift notification
-			@update!
+			this.update();
 
-		@on \update ~>
-			@notifications.for-each (notification) ~>
+		this.on('update', () => {
+			@notifications.for-each (notification) =>
 				date = (new Date notification.created_at).get-date!
 				month = (new Date notification.created_at).get-month! + 1
 				notification._date = date
diff --git a/src/web/app/desktop/tags/pages/entrance.tag b/src/web/app/desktop/tags/pages/entrance.tag
index 57d11217c..227aec388 100644
--- a/src/web/app/desktop/tags/pages/entrance.tag
+++ b/src/web/app/desktop/tags/pages/entrance.tag
@@ -63,18 +63,18 @@
 
 	</style>
 	<script>
-		@mode = \signin
+		this.mode = 'signin' 
 
-		@signup = ~>
-			@mode = \signup
-			@update!
+		signup() {
+			this.mode = 'signup' 
+			this.update();
 
-		@signin = ~>
-			@mode = \signin
-			@update!
+		signin() {
+			this.mode = 'signin' 
+			this.update();
 
-		@introduction = ~>
-			@mode = \introduction
-			@update!
+		introduction() {
+			this.mode = 'introduction' 
+			this.update();
 	</script>
 </mk-entrance>
diff --git a/src/web/app/desktop/tags/pages/entrance/signin.tag b/src/web/app/desktop/tags/pages/entrance/signin.tag
index 1a5baac67..67a449a73 100644
--- a/src/web/app/desktop/tags/pages/entrance/signin.tag
+++ b/src/web/app/desktop/tags/pages/entrance/signin.tag
@@ -119,12 +119,12 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			@refs.signin.on \user (user) ~>
+		this.on('mount', () => {
+			this.refs.signin.on('user', (user) => {
 				@update do
 					user: user
 
-		@introduction = ~>
-			@parent.introduction!
+		introduction() {
+			this.parent.introduction!
 	</script>
 </mk-entrance-signin>
diff --git a/src/web/app/desktop/tags/pages/home.tag b/src/web/app/desktop/tags/pages/home.tag
index 51e576770..348762d2d 100644
--- a/src/web/app/desktop/tags/pages/home.tag
+++ b/src/web/app/desktop/tags/pages/home.tag
@@ -8,40 +8,40 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \api
-		@mixin \ui-progress
-		@mixin \stream
-		@mixin \get-post-summary
+		this.mixin('i');
+		this.mixin('api');
+		this.mixin('ui-progress');
+		this.mixin('stream');
+		this.mixin('get-post-summary');
 
-		@unread-count = 0
+		this.unread-count = 0
 
-		@page = switch @opts.mode
-			| \timelie => \home
-			| \mentions => \mentions
-			| _ => \home
+		this.page = switch this.opts.mode
+			| 'timelie' => 'home' 
+			| 'mentions' => 'mentions' 
+			| _ => 'home' 
 
-		@on \mount ~>
-			@refs.ui.refs.home.on \loaded ~>
-				@Progress.done!
+		this.on('mount', () => {
+			this.refs.ui.refs.home.on('loaded', () => {
+				this.Progress.done();
 
 			document.title = 'Misskey'
-			@Progress.start!
-			@stream.on \post @on-stream-post
-			document.add-event-listener \visibilitychange @window-on-visibilitychange, false
+			this.Progress.start();
+			@stream.on 'post' this.on-stream-post
+			document.add-event-listener 'visibilitychange' @window-on-visibilitychange, false
 
-		@on \unmount ~>
-			@stream.off \post @on-stream-post
-			document.remove-event-listener \visibilitychange @window-on-visibilitychange
+		this.on('unmount', () => {
+			@stream.off 'post' this.on-stream-post
+			document.remove-event-listener 'visibilitychange' @window-on-visibilitychange
 
-		@on-stream-post = (post) ~>
+		on-stream-post(post) {
 			if document.hidden and post.user_id !== @I.id
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
-		@window-on-visibilitychange = ~>
+		window-on-visibilitychange() {
 			if !document.hidden
-				@unread-count = 0
+				this.unread-count = 0
 				document.title = 'Misskey'
 	</script>
 </mk-home-page>
diff --git a/src/web/app/desktop/tags/pages/post.tag b/src/web/app/desktop/tags/pages/post.tag
index fddc21dea..c3298b890 100644
--- a/src/web/app/desktop/tags/pages/post.tag
+++ b/src/web/app/desktop/tags/pages/post.tag
@@ -16,17 +16,17 @@
 
 	</style>
 	<script>
-		@mixin \ui-progress
+		this.mixin('ui-progress');
 
-		@post = @opts.post
+		this.post = this.opts.post
 
-		@on \mount ~>
-			@Progress.start!
+		this.on('mount', () => {
+			this.Progress.start();
 
-			@refs.ui.refs.detail.on \post-fetched ~>
-				@Progress.set 0.5
+			this.refs.ui.refs.detail.on('post-fetched', () => {
+				this.Progress.set(0.5);
 
-			@refs.ui.refs.detail.on \loaded ~>
-				@Progress.done!
+			this.refs.ui.refs.detail.on('loaded', () => {
+				this.Progress.done();
 	</script>
 </mk-post-page>
diff --git a/src/web/app/desktop/tags/pages/search.tag b/src/web/app/desktop/tags/pages/search.tag
index 0c5a23c79..fa0ebee0a 100644
--- a/src/web/app/desktop/tags/pages/search.tag
+++ b/src/web/app/desktop/tags/pages/search.tag
@@ -8,12 +8,12 @@
 
 	</style>
 	<script>
-		@mixin \ui-progress
+		this.mixin('ui-progress');
 
-		@on \mount ~>
-			@Progress.start!
+		this.on('mount', () => {
+			this.Progress.start();
 
-			@refs.ui.refs.search.on \loaded ~>
-				@Progress.done!
+			this.refs.ui.refs.search.on('loaded', () => {
+				this.Progress.done();
 	</script>
 </mk-search-page>
diff --git a/src/web/app/desktop/tags/pages/user.tag b/src/web/app/desktop/tags/pages/user.tag
index be0501e04..3bbfbe859 100644
--- a/src/web/app/desktop/tags/pages/user.tag
+++ b/src/web/app/desktop/tags/pages/user.tag
@@ -8,18 +8,18 @@
 
 	</style>
 	<script>
-		@mixin \ui-progress
+		this.mixin('ui-progress');
 
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@on \mount ~>
-			@Progress.start!
+		this.on('mount', () => {
+			this.Progress.start();
 
-			@refs.ui.refs.user.on \user-fetched (user) ~>
-				@Progress.set 0.5
+			this.refs.ui.refs.user.on('user-fetched', (user) => {
+				this.Progress.set(0.5);
 				document.title = user.name + ' | Misskey'
 
-			@refs.ui.refs.user.on \loaded ~>
-				@Progress.done!
+			this.refs.ui.refs.user.on('loaded', () => {
+				this.Progress.done();
 	</script>
 </mk-user-page>
diff --git a/src/web/app/desktop/tags/post-detail-sub.tag b/src/web/app/desktop/tags/post-detail-sub.tag
index c4a651e37..ccb475c76 100644
--- a/src/web/app/desktop/tags/post-detail-sub.tag
+++ b/src/web/app/desktop/tags/post-detail-sub.tag
@@ -103,38 +103,38 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \text
-		@mixin \date-stringify
-		@mixin \user-preview
+		this.mixin('api');
+		this.mixin('text');
+		this.mixin('date-stringify');
+		this.mixin('user-preview');
 
-		@post = @opts.post
+		this.post = this.opts.post
 
-		@url = CONFIG.url + '/' + @post.user.username + '/' + @post.id
+		this.url = CONFIG.url + '/' + @post.user.username + '/' + @post.id
 
-		@title = @date-stringify @post.created_at
+		this.title = @date-stringify @post.created_at
 
-		@on \mount ~>
+		this.on('mount', () => {
 			if @post.text?
 				tokens = @analyze @post.text
-				@refs.text.innerHTML = @compile tokens
+				this.refs.text.innerHTML = @compile tokens
 
-				@refs.text.children.for-each (e) ~>
-					if e.tag-name == \MK-URL
+				this.refs.text.children.for-each (e) =>
+					if e.tag-name == 'MK-URL' 
 						riot.mount e
 
-		@like = ~>
+		like() {
 			if @post.is_liked
-				@api \posts/likes/delete do
+				this.api 'posts/likes/delete' do
 					post_id: @post.id
-				.then ~>
+				.then =>
 					@post.is_liked = false
-					@update!
+					this.update();
 			else
-				@api \posts/likes/create do
+				this.api 'posts/likes/create' do
 					post_id: @post.id
-				.then ~>
+				.then =>
 					@post.is_liked = true
-					@update!
+					this.update();
 	</script>
 </mk-post-detail-sub>
diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag
index 3c99babaa..0443ff883 100644
--- a/src/web/app/desktop/tags/post-detail.tag
+++ b/src/web/app/desktop/tags/post-detail.tag
@@ -329,108 +329,108 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \text
-		@mixin \user-preview
-		@mixin \date-stringify
-		@mixin \NotImplementedException
+		this.mixin('api');
+		this.mixin('text');
+		this.mixin('user-preview');
+		this.mixin('date-stringify');
+		this.mixin('NotImplementedException');
 
-		@fetching = true
-		@loading-context = false
-		@content = null
-		@post = null
+		this.fetching = true
+		this.loading-context = false
+		this.content = null
+		this.post = null
 
-		@on \mount ~>
+		this.on('mount', () => {
 
-			@api \posts/show do
-				post_id: @opts.post
-			.then (post) ~>
-				@fetching = false
-				@post = post
-				@trigger \loaded
+			this.api 'posts/show' do
+				post_id: this.opts.post
+			.then (post) =>
+				this.fetching = false
+				this.post = post
+				this.trigger('loaded');
 
-				@is-repost = @post.repost?
-				@p = if @is-repost then @post.repost else @post
+				this.is-repost = @post.repost?
+				this.p = if @is-repost then @post.repost else @post
 
-				@title = @date-stringify @p.created_at
+				this.title = @date-stringify @p.created_at
 
-				@update!
+				this.update();
 
 				if @p.text?
 					tokens = @analyze @p.text
-					@refs.text.innerHTML = @compile tokens
+					this.refs.text.innerHTML = @compile tokens
 
-					@refs.text.children.for-each (e) ~>
-						if e.tag-name == \MK-URL
+					this.refs.text.children.for-each (e) =>
+						if e.tag-name == 'MK-URL' 
 							riot.mount e
 
-					# URLをプレビュー
+					// URLをプレビュー
 					tokens
-						.filter (t) -> t.type == \link
-						.map (t) ~>
-							@preview = @refs.text.append-child document.create-element \mk-url-preview
+						.filter (t) -> t.type == 'link' 
+						.map (t) =>
+							this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
 							riot.mount @preview, do
 								url: t.content
 
-				# Get likes
-				@api \posts/likes do
+				// Get likes
+				this.api 'posts/likes' do
 					post_id: @p.id
 					limit: 8
-				.then (likes) ~>
-					@likes = likes
-					@update!
+				.then (likes) =>
+					this.likes = likes
+					this.update();
 
-				# Get reposts
-				@api \posts/reposts do
+				// Get reposts
+				this.api 'posts/reposts' do
 					post_id: @p.id
 					limit: 8
-				.then (reposts) ~>
-					@reposts = reposts
-					@update!
+				.then (reposts) =>
+					this.reposts = reposts
+					this.update();
 
-				# Get replies
-				@api \posts/replies do
+				// Get replies
+				this.api 'posts/replies' do
 					post_id: @p.id
 					limit: 8
-				.then (replies) ~>
-					@replies = replies
-					@update!
+				.then (replies) =>
+					this.replies = replies
+					this.update();
 
-				@update!
+				this.update();
 
-		@reply = ~>
-			form = document.body.append-child document.create-element \mk-post-form-window
+		reply() {
+			form = document.body.appendChild document.createElement 'mk-post-form-window' 
 			riot.mount form, do
 				reply: @p
 
-		@repost = ~>
-			form = document.body.append-child document.create-element \mk-repost-form-window
+		repost() {
+			form = document.body.appendChild document.createElement 'mk-repost-form-window' 
 			riot.mount form, do
 				post: @p
 
-		@like = ~>
+		like() {
 			if @p.is_liked
-				@api \posts/likes/delete do
+				this.api 'posts/likes/delete' do
 					post_id: @p.id
-				.then ~>
+				.then =>
 					@p.is_liked = false
-					@update!
+					this.update();
 			else
-				@api \posts/likes/create do
+				this.api 'posts/likes/create' do
 					post_id: @p.id
-				.then ~>
+				.then =>
 					@p.is_liked = true
-					@update!
+					this.update();
 
-		@load-context = ~>
-			@loading-context = true
+		load-context() {
+			this.loading-context = true
 
-			# Get context
-			@api \posts/context do
+			// Get context
+			this.api 'posts/context' do
 				post_id: @p.reply_to_id
-			.then (context) ~>
-				@context = context.reverse!
-				@loading-context = false
-				@update!
+			.then (context) =>
+				this.context = context.reverse!
+				this.loading-context = false
+				this.update();
 	</script>
 </mk-post-detail>
diff --git a/src/web/app/desktop/tags/post-form-window.tag b/src/web/app/desktop/tags/post-form-window.tag
index fc1a254e2..bb68de5f0 100644
--- a/src/web/app/desktop/tags/post-form-window.tag
+++ b/src/web/app/desktop/tags/post-form-window.tag
@@ -32,24 +32,24 @@
 
 	</style>
 	<script>
-		@uploading-files = []
-		@files = []
+		this.uploading-files = []
+		this.files = []
 
-		@on \mount ~>
-			@refs.window.refs.form.focus!
+		this.on('mount', () => {
+			this.refs.window.refs.form.focus();
 
-			@refs.window.on \closed ~>
-				@unmount!
+			this.refs.window.on('closed', () => {
+				this.unmount();
 
-			@refs.window.refs.form.on \post ~>
-				@refs.window.close!
+			this.refs.window.refs.form.on('post', () => {
+				this.refs.window.close!
 
-			@refs.window.refs.form.on \change-uploading-files (files) ~>
-				@uploading-files = files
-				@update!
+			this.refs.window.refs.form.on('change-uploading-files', (files) => {
+				this.uploading-files = files
+				this.update();
 
-			@refs.window.refs.form.on \change-files (files) ~>
-				@files = files
-				@update!
+			this.refs.window.refs.form.on('change-files', (files) => {
+				this.files = files
+				this.update();
 	</script>
 </mk-post-form-window>
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index a0b6ea7d0..760a585ce 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -305,161 +305,161 @@
 
 	</style>
 	<script>
-		get-cat = require '../../common/scripts/get-cat'
+		get-cat = require('../../common/scripts/get-cat');
 
-		@mixin \api
-		@mixin \notify
-		@mixin \autocomplete
+		this.mixin('api');
+		this.mixin('notify');
+		this.mixin('autocomplete');
 
-		@wait = false
-		@uploadings = []
-		@files = []
-		@autocomplete = null
-		@poll = false
+		this.wait = false
+		this.uploadings = []
+		this.files = []
+		this.autocomplete = null
+		this.poll = false
 
-		@in-reply-to-post = @opts.reply
+		this.in-reply-to-post = this.opts.reply
 
-		# https://github.com/riot/riot/issues/2080
-		if @in-reply-to-post == '' then @in-reply-to-post = null
+		// https://github.com/riot/riot/issues/2080
+		if @in-reply-to-post == '' then this.in-reply-to-post = null
 
-		@on \mount ~>
-			@refs.uploader.on \uploaded (file) ~>
+		this.on('mount', () => {
+			this.refs.uploader.on('uploaded', (file) => {
 				@add-file file
 
-			@refs.uploader.on \change-uploads (uploads) ~>
-				@trigger \change-uploading-files uploads
+			this.refs.uploader.on('change-uploads', (uploads) => {
+				this.trigger 'change-uploading-files' uploads
 
-			@autocomplete = new @Autocomplete @refs.text
+			this.autocomplete = new @Autocomplete this.refs.text
 			@autocomplete.attach!
 
-		@on \unmount ~>
+		this.on('unmount', () => {
 			@autocomplete.detach!
 
-		@focus = ~>
-			@refs.text.focus!
+		focus() {
+			this.refs.text.focus();
 
-		@clear = ~>
-			@refs.text.value = ''
-			@files = []
-			@trigger \change-files
-			@update!
+		clear() {
+			this.refs.text.value = ''
+			this.files = []
+			this.trigger('change-files');
+			this.update();
 
-		@ondragover = (e) ~>
+		ondragover(e) {
 			e.stop-propagation!
-			@draghover = true
-			# ドラッグされてきたものがファイルだったら
-			if e.data-transfer.effect-allowed == \all
-				e.data-transfer.drop-effect = \copy
+			this.draghover = true
+			// ドラッグされてきたものがファイルだったら
+			if e.data-transfer.effect-allowed == 'all' 
+				e.data-transfer.drop-effect = 'copy' 
 			else
-				e.data-transfer.drop-effect = \move
+				e.data-transfer.drop-effect = 'move' 
 			return false
 
-		@ondragenter = (e) ~>
-			@draghover = true
+		ondragenter(e) {
+			this.draghover = true
 
-		@ondragleave = (e) ~>
-			@draghover = false
+		ondragleave(e) {
+			this.draghover = false
 
-		@ondrop = (e) ~>
+		ondrop(e) {
 			e.prevent-default!
 			e.stop-propagation!
-			@draghover = false
+			this.draghover = false
 
-			# ファイルだったら
+			// ファイルだったら
 			if e.data-transfer.files.length > 0
-				Array.prototype.for-each.call e.data-transfer.files, (file) ~>
+				Array.prototype.for-each.call e.data-transfer.files, (file) =>
 					@upload file
 				return false
 
-			# データ取得
+			// データ取得
 			data = e.data-transfer.get-data 'text'
 			if !data?
 				return false
 
 			try
-				# パース
+				// パース
 				obj = JSON.parse data
 
-				# (ドライブの)ファイルだったら
-				if obj.type == \file
+				// (ドライブの)ファイルだったら
+				if obj.type == 'file' 
 					@add-file obj.file
 			catch
-				# ignore
+				// ignore
 
 			return false
 
-		@onkeydown = (e) ~>
-			if (e.which == 10 || e.which == 13) && (e.ctrl-key || e.meta-key)
+		onkeydown(e) {
+			if (e.which == 10 || e.which == 13) && (e.ctrlKey || e.meta-key)
 				@post!
 
-		@onpaste = (e) ~>
-			data = e.clipboard-data
+		onpaste(e) {
+			data = e.clipboardData
 			items = data.items
 			for i from 0 to items.length - 1
 				item = items[i]
 				switch (item.kind)
-					| \file =>
-						@upload item.get-as-file!
+					| 'file' =>
+						@upload item.getAsFile();
 
-		@select-file = ~>
-			@refs.file.click!
+		select-file() {
+			this.refs.file.click!
 
-		@select-file-from-drive = ~>
-			browser = document.body.append-child document.create-element \mk-select-file-from-drive-window
+		select-file-from-drive() {
+			browser = document.body.appendChild document.createElement 'mk-select-file-from-drive-window' 
 			i = riot.mount browser, do
 				multiple: true
-			i[0].one \selected (files) ~>
+			i[0].one 'selected' (files) =>
 				files.for-each @add-file
 
-		@change-file = ~>
-			files = @refs.file.files
+		change-file() {
+			files = this.refs.file.files
 			for i from 0 to files.length - 1
 				file = files.item i
 				@upload file
 
-		@upload = (file) ~>
-			@refs.uploader.upload file
+		upload(file) {
+			this.refs.uploader.upload file
 
-		@add-file = (file) ~>
-			file._remove = ~>
-				@files = @files.filter (x) -> x.id != file.id
-				@trigger \change-files @files
-				@update!
+		add-file(file) {
+			file._remove = =>
+				this.files = @files.filter (x) -> x.id != file.id
+				this.trigger 'change-files' @files
+				this.update();
 
 			@files.push file
-			@trigger \change-files @files
-			@update!
+			this.trigger 'change-files' @files
+			this.update();
 
-		@add-poll = ~>
-			@poll = true
+		add-poll() {
+			this.poll = true
 
-		@on-poll-destroyed = ~>
+		on-poll-destroyed() {
 			@update do
 				poll: false
 
-		@post = (e) ~>
-			@wait = true
+		post(e) {
+			this.wait = true
 
 			files = if @files? and @files.length > 0
 				then @files.map (f) -> f.id
 				else undefined
 
-			@api \posts/create do
-				text: @refs.text.value
+			this.api 'posts/create' do
+				text: this.refs.text.value
 				media_ids: files
 				reply_to_id: if @in-reply-to-post? then @in-reply-to-post.id else undefined
-				poll: if @poll then @refs.poll.get! else undefined
-			.then (data) ~>
-				@trigger \post
+				poll: if @poll then this.refs.poll.get! else undefined
+			.then (data) =>
+				this.trigger('post');
 				@notify if @in-reply-to-post? then '返信しました!' else '投稿しました!'
-			.catch (err) ~>
+			.catch (err) =>
 				console.error err
 				@notify '投稿できませんでした'
-			.then ~>
-				@wait = false
-				@update!
+			.then =>
+				this.wait = false
+				this.update();
 
-		@cat = ~>
-			@refs.text.value = @refs.text.value + get-cat!
+		cat() {
+			this.refs.text.value = this.refs.text.value + get-cat!
 	</script>
 </mk-post-form>
diff --git a/src/web/app/desktop/tags/post-preview.tag b/src/web/app/desktop/tags/post-preview.tag
index c0514c323..5ee0a6065 100644
--- a/src/web/app/desktop/tags/post-preview.tag
+++ b/src/web/app/desktop/tags/post-preview.tag
@@ -83,11 +83,11 @@
 
 	</style>
 	<script>
-		@mixin \date-stringify
-		@mixin \user-preview
+		this.mixin('date-stringify');
+		this.mixin('user-preview');
 
-		@post = @opts.post
+		this.post = this.opts.post
 
-		@title = @date-stringify @post.created_at
+		this.title = @date-stringify @post.created_at
 	</script>
 </mk-post-preview>
diff --git a/src/web/app/desktop/tags/post-status-graph.tag b/src/web/app/desktop/tags/post-status-graph.tag
index f7c6ea7b1..039c676b1 100644
--- a/src/web/app/desktop/tags/post-status-graph.tag
+++ b/src/web/app/desktop/tags/post-status-graph.tag
@@ -9,64 +9,64 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
+		this.mixin('api');
+		this.mixin('is-promise');
 
-		@post = null
-		@post-promise = if @is-promise @opts.post then @opts.post else Promise.resolve @opts.post
+		this.post = null
+		this.post-promise = if @is-promise this.opts.post then this.opts.post else Promise.resolve this.opts.post
 
-		@on \mount ~>
+		this.on('mount', () => {
 			post <~ @post-promise.then
-			@post = post
-			@update!
+			this.post = post
+			this.update();
 
-			@api \aggregation/posts/like do
+			this.api 'aggregation/posts/like' do
 				post_id: @post.id
 				limit: 30days
-			.then (likes) ~>
+			.then (likes) =>
 				likes = likes.reverse!
 
-				@api \aggregation/posts/repost do
+				this.api 'aggregation/posts/repost' do
 					post_id: @post.id
 					limit: 30days
-				.then (repost) ~>
+				.then (repost) =>
 					repost = repost.reverse!
 
-					@api \aggregation/posts/reply do
+					this.api 'aggregation/posts/reply' do
 						post_id: @post.id
 						limit: 30days
-					.then (replies) ~>
+					.then (replies) =>
 						replies = replies.reverse!
 
-						new Chart @refs.canv, do
-							type: \bar
+						new Chart this.refs.canv, do
+							type: 'bar' 
 							data:
-								labels: likes.map (x, i) ~> if i % 3 == 2 then x.date.day + '日' else ''
+								labels: likes.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
 								datasets: [
 									{
-										label: \いいね
-										type: \line
-										data: likes.map (x) ~> x.count
+										label: 'いいね' 
+										type: 'line' 
+										data: likes.map (x) => x.count
 										line-tension: 0
 										border-width: 2
 										fill: true
 										background-color: 'rgba(247, 121, 108, 0.2)'
-										point-background-color: \#fff
+										point-background-color: '#fff' 
 										point-radius: 4
 										point-border-width: 2
-										border-color: \#F7796C
+										border-color: '#F7796C' 
 									},
 									{
-										label: \返信
-										type: \bar
-										data: replies.map (x) ~> x.count
-										background-color: \#555
+										label: '返信' 
+										type: 'bar' 
+										data: replies.map (x) => x.count
+										background-color: '#555' 
 									},
 									{
-										label: \Repost
-										type: \bar
-										data: repost.map (x) ~> x.count
-										background-color: \#a2d61e
+										label: 'Repost' 
+										type: 'bar' 
+										data: repost.map (x) => x.count
+										background-color: '#a2d61e' 
 									}
 								]
 							options:
diff --git a/src/web/app/desktop/tags/progress-dialog.tag b/src/web/app/desktop/tags/progress-dialog.tag
index c60746257..bb5dea8b4 100644
--- a/src/web/app/desktop/tags/progress-dialog.tag
+++ b/src/web/app/desktop/tags/progress-dialog.tag
@@ -75,20 +75,20 @@
 
 	</style>
 	<script>
-		@title = @opts.title
-		@value = parse-int @opts.value, 10
-		@max = parse-int @opts.max, 10
+		this.title = this.opts.title
+		this.value = parse-int this.opts.value, 10
+		this.max = parse-int this.opts.max, 10
 
-		@on \mount ~>
-			@refs.window.on \closed ~>
-				@unmount!
+		this.on('mount', () => {
+			this.refs.window.on('closed', () => {
+				this.unmount();
 
-		@update-progress = (value, max) ~>
-			@value = parse-int value, 10
-			@max = parse-int max, 10
-			@update!
+		update-progress(value, max) {
+			this.value = parse-int value, 10
+			this.max = parse-int max, 10
+			this.update();
 
-		@close = ~>
-			@refs.window.close!
+		close() {
+			this.refs.window.close!
 	</script>
 </mk-progress-dialog>
diff --git a/src/web/app/desktop/tags/repost-form-window.tag b/src/web/app/desktop/tags/repost-form-window.tag
index 45a0cdae6..d66f98bb8 100644
--- a/src/web/app/desktop/tags/repost-form-window.tag
+++ b/src/web/app/desktop/tags/repost-form-window.tag
@@ -12,25 +12,25 @@
 
 	</style>
 	<script>
-		@on-document-keydown = (e) ~>
+		on-document-keydown(e) {
 			tag = e.target.tag-name.to-lower-case!
-			if tag != \input and tag != \textarea
-				if e.which == 27 # Esc
-					@refs.window.close!
+			if tag != 'input' and tag != 'textarea' 
+				if e.which == 27 // Esc
+					this.refs.window.close!
 
-		@on \mount ~>
-			@refs.window.refs.form.on \cancel ~>
-				@refs.window.close!
+		this.on('mount', () => {
+			this.refs.window.refs.form.on('cancel', () => {
+				this.refs.window.close!
 
-			@refs.window.refs.form.on \posted ~>
-				@refs.window.close!
+			this.refs.window.refs.form.on('posted', () => {
+				this.refs.window.close!
 
-			document.add-event-listener \keydown @on-document-keydown
+			document.add-event-listener 'keydown' this.on-document-keydown
 
-			@refs.window.on \closed ~>
-				@unmount!
+			this.refs.window.on('closed', () => {
+				this.unmount();
 
-		@on \unmount ~>
-			document.remove-event-listener \keydown @on-document-keydown
+		this.on('unmount', () => {
+			document.remove-event-listener 'keydown' this.on-document-keydown
 	</script>
 </mk-repost-form-window>
diff --git a/src/web/app/desktop/tags/repost-form.tag b/src/web/app/desktop/tags/repost-form.tag
index 2c07ff4b1..58ef564ba 100644
--- a/src/web/app/desktop/tags/repost-form.tag
+++ b/src/web/app/desktop/tags/repost-form.tag
@@ -114,31 +114,31 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \notify
+		this.mixin('api');
+		this.mixin('notify');
 
-		@wait = false
-		@quote = false
+		this.wait = false
+		this.quote = false
 
-		@cancel = ~>
-			@trigger \cancel
+		cancel() {
+			this.trigger('cancel');
 
-		@ok = ~>
-			@wait = true
-			@api \posts/create do
-				repost_id: @opts.post.id
-				text: if @quote then @refs.text.value else undefined
-			.then (data) ~>
-				@trigger \posted
+		ok() {
+			this.wait = true
+			this.api 'posts/create' do
+				repost_id: this.opts.post.id
+				text: if @quote then this.refs.text.value else undefined
+			.then (data) =>
+				this.trigger('posted');
 				@notify 'Repostしました!'
-			.catch (err) ~>
+			.catch (err) =>
 				console.error err
 				@notify 'Repostできませんでした'
-			.then ~>
-				@wait = false
-				@update!
+			.then =>
+				this.wait = false
+				this.update();
 
-		@onquote = ~>
-			@quote = true
+		onquote() {
+			this.quote = true
 	</script>
 </mk-repost-form>
diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag
index 2cc9b788a..a61a0a061 100644
--- a/src/web/app/desktop/tags/search-posts.tag
+++ b/src/web/app/desktop/tags/search-posts.tag
@@ -28,59 +28,59 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \get-post-summary
+		this.mixin('api');
+		this.mixin('get-post-summary');
 
-		@query = @opts.query
-		@is-loading = true
-		@is-empty = false
-		@more-loading = false
-		@page = 0
+		this.query = this.opts.query
+		this.is-loading = true
+		this.is-empty = false
+		this.more-loading = false
+		this.page = 0
 
-		@on \mount ~>
-			document.add-event-listener \keydown @on-document-keydown
-			window.add-event-listener \scroll @on-scroll
+		this.on('mount', () => {
+			document.add-event-listener 'keydown' this.on-document-keydown
+			window.add-event-listener 'scroll' this.on-scroll
 
-			@api \posts/search do
+			this.api 'posts/search' do
 				query: @query
-			.then (posts) ~>
-				@is-loading = false
-				@is-empty = posts.length == 0
-				@update!
-				@refs.timeline.set-posts posts
-				@trigger \loaded
-			.catch (err) ~>
+			.then (posts) =>
+				this.is-loading = false
+				this.is-empty = posts.length == 0
+				this.update();
+				this.refs.timeline.set-posts posts
+				this.trigger('loaded');
+			.catch (err) =>
 				console.error err
 
-		@on \unmount ~>
-			document.remove-event-listener \keydown @on-document-keydown
-			window.remove-event-listener \scroll @on-scroll
+		this.on('unmount', () => {
+			document.remove-event-listener 'keydown' this.on-document-keydown
+			window.remove-event-listener 'scroll' this.on-scroll
 
-		@on-document-keydown = (e) ~>
+		on-document-keydown(e) {
 			tag = e.target.tag-name.to-lower-case!
-			if tag != \input and tag != \textarea
-				if e.which == 84 # t
-					@refs.timeline.focus!
+			if tag != 'input' and tag != 'textarea' 
+				if e.which == 84 // t
+					this.refs.timeline.focus();
 
-		@more = ~>
+		more() {
 			if @more-loading or @is-loading or @timeline.posts.length == 0
 				return
-			@more-loading = true
-			@update!
-			@api \posts/search do
+			this.more-loading = true
+			this.update();
+			this.api 'posts/search' do
 				query: @query
 				page: @page + 1
-			.then (posts) ~>
-				@more-loading = false
+			.then (posts) =>
+				this.more-loading = false
 				@page++
-				@update!
-				@refs.timeline.prepend-posts posts
-			.catch (err) ~>
+				this.update();
+				this.refs.timeline.prepend-posts posts
+			.catch (err) =>
 				console.error err
 
-		@on-scroll = ~>
+		on-scroll() {
 			current = window.scroll-y + window.inner-height
-			if current > document.body.offset-height - 16 # 遊び
+			if current > document.body.offset-height - 16 // 遊び
 				@more!
 	</script>
 </mk-search-posts>
diff --git a/src/web/app/desktop/tags/search.tag b/src/web/app/desktop/tags/search.tag
index d2561dfdc..82a1d7986 100644
--- a/src/web/app/desktop/tags/search.tag
+++ b/src/web/app/desktop/tags/search.tag
@@ -23,10 +23,10 @@
 
 	</style>
 	<script>
-		@query = @opts.query
+		this.query = this.opts.query
 
-		@on \mount ~>
-			@refs.posts.on \loaded ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			this.refs.posts.on('loaded', () => {
+				this.trigger('loaded');
 	</script>
 </mk-search>
diff --git a/src/web/app/desktop/tags/select-file-from-drive-window.tag b/src/web/app/desktop/tags/select-file-from-drive-window.tag
index f9ba9e3cc..f4cfd5503 100644
--- a/src/web/app/desktop/tags/select-file-from-drive-window.tag
+++ b/src/web/app/desktop/tags/select-file-from-drive-window.tag
@@ -131,31 +131,31 @@
 
 	</style>
 	<script>
-		@file = []
+		this.file = []
 
-		@multiple = if @opts.multiple? then @opts.multiple else false
-		@title = @opts.title || '<i class="fa fa-file-o"></i>ファイルを選択'
+		this.multiple = if this.opts.multiple? then this.opts.multiple else false
+		this.title = this.opts.title || '<i class="fa fa-file-o"></i>ファイルを選択'
 
-		@on \mount ~>
-			@refs.window.refs.browser.on \selected (file) ~>
-				@file = file
+		this.on('mount', () => {
+			this.refs.window.refs.browser.on('selected', (file) => {
+				this.file = file
 				@ok!
 
-			@refs.window.refs.browser.on \change-selection (files) ~>
-				@file = files
-				@update!
+			this.refs.window.refs.browser.on('change-selection', (files) => {
+				this.file = files
+				this.update();
 
-			@refs.window.on \closed ~>
-				@unmount!
+			this.refs.window.on('closed', () => {
+				this.unmount();
 
-		@close = ~>
-			@refs.window.close!
+		close() {
+			this.refs.window.close!
 
-		@upload = ~>
-			@refs.window.refs.browser.select-local-file!
+		upload() {
+			this.refs.window.refs.browser.select-local-file!
 
-		@ok = ~>
-			@trigger \selected @file
-			@refs.window.close!
+		ok() {
+			this.trigger 'selected' @file
+			this.refs.window.close!
 	</script>
 </mk-select-file-from-drive-window>
diff --git a/src/web/app/desktop/tags/set-avatar-suggestion.tag b/src/web/app/desktop/tags/set-avatar-suggestion.tag
index 22a0de0f3..858838743 100644
--- a/src/web/app/desktop/tags/set-avatar-suggestion.tag
+++ b/src/web/app/desktop/tags/set-avatar-suggestion.tag
@@ -31,15 +31,15 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \update-avatar
+		this.mixin('i');
+		this.mixin('update-avatar');
 
-		@set = ~>
+		set() {
 			@update-avatar @I
 
-		@close = (e) ~>
+		close(e) {
 			e.prevent-default!
 			e.stop-propagation!
-			@unmount!
+			this.unmount();
 	</script>
 </mk-set-avatar-suggestion>
diff --git a/src/web/app/desktop/tags/set-banner-suggestion.tag b/src/web/app/desktop/tags/set-banner-suggestion.tag
index 3ccaab108..2a4ba8dbb 100644
--- a/src/web/app/desktop/tags/set-banner-suggestion.tag
+++ b/src/web/app/desktop/tags/set-banner-suggestion.tag
@@ -31,15 +31,15 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \update-banner
+		this.mixin('i');
+		this.mixin('update-banner');
 
-		@set = ~>
+		set() {
 			@update-banner @I
 
-		@close = (e) ~>
+		close(e) {
 			e.prevent-default!
 			e.stop-propagation!
-			@unmount!
+			this.unmount();
 	</script>
 </mk-set-banner-suggestion>
diff --git a/src/web/app/desktop/tags/settings-window.tag b/src/web/app/desktop/tags/settings-window.tag
index 10bb48de7..4ffc5f225 100644
--- a/src/web/app/desktop/tags/settings-window.tag
+++ b/src/web/app/desktop/tags/settings-window.tag
@@ -15,11 +15,11 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			@refs.window.on \closed ~>
-				@unmount!
+		this.on('mount', () => {
+			this.refs.window.on('closed', () => {
+				this.unmount();
 
-		@close = ~>
-			@refs.window.close!
+		close() {
+			this.refs.window.close!
 	</script>
 </mk-settings-window>
diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag
index 1c14514ac..16369c2f4 100644
--- a/src/web/app/desktop/tags/settings.tag
+++ b/src/web/app/desktop/tags/settings.tag
@@ -198,45 +198,45 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \api
-		@mixin \dialog
-		@mixin \update-avatar
+		this.mixin('i');
+		this.mixin('api');
+		this.mixin('dialog');
+		this.mixin('update-avatar');
 
-		@page = \account
+		this.page = 'account' 
 
-		@set-page = (page) ~>
-			@page = page
+		set-page(page) {
+			this.page = page
 
-		@avatar = ~>
+		avatar() {
 			@update-avatar @I
 
-		@update-account = ~>
-			@api \i/update do
-				name: @refs.account-name.value
-				location: @refs.account-location.value
-				bio: @refs.account-bio.value
-				birthday: @refs.account-birthday.value
-			.then (i) ~>
-				alert \ok
-			.catch (err) ~>
+		update-account() {
+			this.api 'i/update' do
+				name: this.refs.account-name.value
+				location: this.refs.account-location.value
+				bio: this.refs.account-bio.value
+				birthday: this.refs.account-birthday.value
+			.then (i) =>
+				alert 'ok' 
+			.catch (err) =>
 				console.error err
 
-		@update-cache = ~>
+		update-cache() {
 			@I.data.cache = !@I.data.cache
-			@api \i/appdata/set do
+			this.api 'i/appdata/set' do
 				data: JSON.stringify do
 					cache: @I.data.cache
 
-		@update-debug = ~>
+		update-debug() {
 			@I.data.debug = !@I.data.debug
-			@api \i/appdata/set do
+			this.api 'i/appdata/set' do
 				data: JSON.stringify do
 					debug: @I.data.debug
 
-		@update-nya = ~>
+		update-nya() {
 			@I.data.nya = !@I.data.nya
-			@api \i/appdata/set do
+			this.api 'i/appdata/set' do
 				data: JSON.stringify do
 					nya: @I.data.nya
 	</script>
diff --git a/src/web/app/desktop/tags/stream-indicator.tag b/src/web/app/desktop/tags/stream-indicator.tag
index d2ab34574..caa727dd8 100644
--- a/src/web/app/desktop/tags/stream-indicator.tag
+++ b/src/web/app/desktop/tags/stream-indicator.tag
@@ -27,27 +27,27 @@
 
 	</style>
 	<script>
-		@mixin \stream
+		this.mixin('stream');
 
-		@on \before-mount ~>
-			@state = @get-stream-state!
+		this.on('before-mount', () => {
+			this.state = @get-stream-state!
 
-			if @state == \connected
-				@root.style.opacity = 0
+			if @state == 'connected' 
+				this.root.style.opacity = 0
 
-		@stream-state-ev.on \connected ~>
-			@state = @get-stream-state!
-			@update!
-			set-timeout ~>
-				Velocity @root, {
+		@stream-state-ev.on('connected', () => {
+			this.state = @get-stream-state!
+			this.update();
+			setTimeout =>
+				Velocity this.root, {
 					opacity: 0
-				} 200ms \linear
+				} 200ms 'linear' 
 			, 1000ms
 
-		@stream-state-ev.on \closed ~>
-			@state = @get-stream-state!
-			@update!
-			Velocity @root, {
+		@stream-state-ev.on('closed', () => {
+			this.state = @get-stream-state!
+			this.update();
+			Velocity this.root, {
 				opacity: 1
 			} 0ms
 	</script>
diff --git a/src/web/app/desktop/tags/sub-post-content.tag b/src/web/app/desktop/tags/sub-post-content.tag
index 72f570dd6..0fdd049ec 100644
--- a/src/web/app/desktop/tags/sub-post-content.tag
+++ b/src/web/app/desktop/tags/sub-post-content.tag
@@ -28,18 +28,18 @@
 
 	</style>
 	<script>
-		@mixin \text
-		@mixin \user-preview
+		this.mixin('text');
+		this.mixin('user-preview');
 
-		@post = @opts.post
+		this.post = this.opts.post
 
-		@on \mount ~>
+		this.on('mount', () => {
 			if @post.text?
 				tokens = @analyze @post.text
-				@refs.text.innerHTML = @compile tokens, false
+				this.refs.text.innerHTML = @compile tokens, false
 
-				@refs.text.children.for-each (e) ~>
-					if e.tag-name == \MK-URL
+				this.refs.text.children.for-each (e) =>
+					if e.tag-name == 'MK-URL' 
 						riot.mount e
 	</script>
 </mk-sub-post-content>
diff --git a/src/web/app/desktop/tags/timeline-post-sub.tag b/src/web/app/desktop/tags/timeline-post-sub.tag
index 5884927d7..bdeffea18 100644
--- a/src/web/app/desktop/tags/timeline-post-sub.tag
+++ b/src/web/app/desktop/tags/timeline-post-sub.tag
@@ -9,12 +9,12 @@
 		</div>
 	</article>
 	<script>
-		@mixin \date-stringify
-		@mixin \user-preview
+		this.mixin('date-stringify');
+		this.mixin('user-preview');
 
-		@post = @opts.post
+		this.post = this.opts.post
 
-		@title = @date-stringify @post.created_at
+		this.title = @date-stringify @post.created_at
 
 	</script>
 	<style>
diff --git a/src/web/app/desktop/tags/timeline-post.tag b/src/web/app/desktop/tags/timeline-post.tag
index 1549151fd..8ccf2b57c 100644
--- a/src/web/app/desktop/tags/timeline-post.tag
+++ b/src/web/app/desktop/tags/timeline-post.tag
@@ -312,83 +312,83 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \text
-		@mixin \date-stringify
-		@mixin \user-preview
-		@mixin \NotImplementedException
+		this.mixin('api');
+		this.mixin('text');
+		this.mixin('date-stringify');
+		this.mixin('user-preview');
+		this.mixin('NotImplementedException');
 
-		@post = @opts.post
-		@is-repost = @post.repost? and !@post.text?
-		@p = if @is-repost then @post.repost else @post
+		this.post = this.opts.post
+		this.is-repost = @post.repost? and !@post.text?
+		this.p = if @is-repost then @post.repost else @post
 
-		@title = @date-stringify @p.created_at
+		this.title = @date-stringify @p.created_at
 
-		@url = CONFIG.url + '/' + @p.user.username + '/' + @p.id
-		@is-detail-opened = false
+		this.url = CONFIG.url + '/' + @p.user.username + '/' + @p.id
+		this.is-detail-opened = false
 
-		@on \mount ~>
+		this.on('mount', () => {
 			if @p.text?
 				tokens = if @p._highlight?
 					then @analyze @p._highlight
 					else @analyze @p.text
 
-				@refs.text.innerHTML = @refs.text.innerHTML.replace '<p class="dummy"></p>' if @p._highlight?
+				this.refs.text.innerHTML = this.refs.text.innerHTML.replace '<p class="dummy"></p>' if @p._highlight?
 					then @compile tokens, true, false
 					else @compile tokens
 
-				@refs.text.children.for-each (e) ~>
-					if e.tag-name == \MK-URL
+				this.refs.text.children.for-each (e) =>
+					if e.tag-name == 'MK-URL' 
 						riot.mount e
 
-				# URLをプレビュー
+				// URLをプレビュー
 				tokens
-					.filter (t) -> t.type == \link
-					.map (t) ~>
-						@preview = @refs.text.append-child document.create-element \mk-url-preview
+					.filter (t) -> t.type == 'link' 
+					.map (t) =>
+						this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
 						riot.mount @preview, do
 							url: t.content
 
-		@reply = ~>
-			form = document.body.append-child document.create-element \mk-post-form-window
+		reply() {
+			form = document.body.appendChild document.createElement 'mk-post-form-window' 
 			riot.mount form, do
 				reply: @p
 
-		@repost = ~>
-			form = document.body.append-child document.create-element \mk-repost-form-window
+		repost() {
+			form = document.body.appendChild document.createElement 'mk-repost-form-window' 
 			riot.mount form, do
 				post: @p
 
-		@like = ~>
+		like() {
 			if @p.is_liked
-				@api \posts/likes/delete do
+				this.api 'posts/likes/delete' do
 					post_id: @p.id
-				.then ~>
+				.then =>
 					@p.is_liked = false
-					@update!
+					this.update();
 			else
-				@api \posts/likes/create do
+				this.api 'posts/likes/create' do
 					post_id: @p.id
-				.then ~>
+				.then =>
 					@p.is_liked = true
-					@update!
+					this.update();
 
-		@toggle-detail = ~>
-			@is-detail-opened = !@is-detail-opened
-			@update!
+		toggle-detail() {
+			this.is-detail-opened = !@is-detail-opened
+			this.update();
 
-		@on-key-down = (e) ~>
+		on-key-down(e) {
 			should-be-cancel = true
 			switch
-			| e.which == 38 or e.which == 74 or (e.which == 9 and e.shift-key) => # ↑, j or Shift+Tab
-				focus @root, (e) -> e.previous-element-sibling
-			| e.which == 40 or e.which == 75 or e.which == 9 => # ↓, k or Tab
-				focus @root, (e) -> e.next-element-sibling
-			| e.which == 81 or e.which == 69 => # q or e
+			| e.which == 38 or e.which == 74 or (e.which == 9 and e.shift-key) => // ↑, j or Shift+Tab
+				focus this.root, (e) -> e.previous-element-sibling
+			| e.which == 40 or e.which == 75 or e.which == 9 => // ↓, k or Tab
+				focus this.root, (e) -> e.next-element-sibling
+			| e.which == 81 or e.which == 69 => // q or e
 				@repost!
-			| e.which == 70 or e.which == 76 => # f or l
+			| e.which == 70 or e.which == 76 => // f or l
 				@like!
-			| e.which == 82 => # r
+			| e.which == 82 => // r
 				@reply!
 			| _ =>
 				should-be-cancel = false
@@ -399,8 +399,8 @@
 		function focus(el, fn)
 			target = fn el
 			if target?
-				if target.has-attribute \tabindex
-					target.focus!
+				if target.has-attribute 'tabindex' 
+					target.focus();
 				else
 					focus target, fn
 	</script>
diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag
index 3439a426e..5967c2efd 100644
--- a/src/web/app/desktop/tags/timeline.tag
+++ b/src/web/app/desktop/tags/timeline.tag
@@ -44,36 +44,36 @@
 
 	</style>
 	<script>
-		@posts = []
+		this.posts = []
 
-		@set-posts = (posts) ~>
-			@posts = posts
-			@update!
+		set-posts(posts) {
+			this.posts = posts
+			this.update();
 
-		@prepend-posts = (posts) ~>
-			posts.for-each (post) ~>
+		prepend-posts(posts) {
+			posts.for-each (post) =>
 				@posts.push post
-				@update!
+				this.update();
 
-		@add-post = (post) ~>
+		add-post(post) {
 			@posts.unshift post
-			@update!
+			this.update();
 
-		@clear = ~>
-			@posts = []
-			@update!
+		clear() {
+			this.posts = []
+			this.update();
 
-		@focus = ~>
-			@root.children.0.focus!
+		focus() {
+			this.root.children.0.focus();
 
-		@on \update ~>
-			@posts.for-each (post) ~>
+		this.on('update', () => {
+			@posts.for-each (post) =>
 				date = (new Date post.created_at).get-date!
 				month = (new Date post.created_at).get-month! + 1
 				post._date = date
 				post._datetext = month + '月 ' + date + '日'
 
-		@tail = ~>
+		tail() {
 			@posts[@posts.length - 1]
 	</script>
 </mk-timeline>
diff --git a/src/web/app/desktop/tags/ui-header-account.tag b/src/web/app/desktop/tags/ui-header-account.tag
index 6071995ce..a5308b014 100644
--- a/src/web/app/desktop/tags/ui-header-account.tag
+++ b/src/web/app/desktop/tags/ui-header-account.tag
@@ -159,47 +159,47 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \signout
+		this.mixin('i');
+		this.mixin('signout');
 
-		@is-open = false
+		this.is-open = false
 
-		@on \before-unmount ~>
+		this.on('before-unmount', () => {
 			@close!
 
-		@toggle = ~>
+		toggle() {
 			if @is-open
 				@close!
 			else
 				@open!
 
-		@open = ~>
-			@is-open = true
-			@update!
+		open() {
+			this.is-open = true
+			this.update();
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) ~>
-				el.add-event-listener \mousedown @mousedown
+			Array.prototype.for-each.call all, (el) =>
+				el.add-event-listener 'mousedown' @mousedown
 
-		@close = ~>
-			@is-open = false
-			@update!
+		close() {
+			this.is-open = false
+			this.update();
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) ~>
-				el.remove-event-listener \mousedown @mousedown
+			Array.prototype.for-each.call all, (el) =>
+				el.remove-event-listener 'mousedown' @mousedown
 
-		@mousedown = (e) ~>
+		mousedown(e) {
 			e.prevent-default!
-			if (!contains @root, e.target) and (@root != e.target)
+			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 			return false
 
-		@drive = ~>
+		drive() {
 			@close!
-			riot.mount document.body.append-child document.create-element \mk-drive-browser-window
+			riot.mount document.body.appendChild document.createElement 'mk-drive-browser-window' 
 
-		@settings = ~>
+		settings() {
 			@close!
-			riot.mount document.body.append-child document.create-element \mk-settings-window
+			riot.mount document.body.appendChild document.createElement 'mk-settings-window' 
 
 		function contains(parent, child)
 			node = child.parent-node
diff --git a/src/web/app/desktop/tags/ui-header-clock.tag b/src/web/app/desktop/tags/ui-header-clock.tag
index 50536705b..339951fb6 100644
--- a/src/web/app/desktop/tags/ui-header-clock.tag
+++ b/src/web/app/desktop/tags/ui-header-clock.tag
@@ -58,7 +58,7 @@
 
 	</style>
 	<script>
-		@draw = ~>
+		draw() {
 			now = new Date!
 
 			yyyy = now.get-full-year!
@@ -71,17 +71,17 @@
 			hhmm = "<span class='hhmm'>#hh:#mm</span>"
 
 			if now.get-seconds! % 2 == 0
-				hhmm .= replace \: '<span style=\'visibility:visible\'>:</span>'
+				hhmm .= replace ':' '<span style=\'visibility:visible\'>:</span>'
 			else
-				hhmm .= replace \: '<span style=\'visibility:hidden\'>:</span>'
+				hhmm .= replace ':' '<span style=\'visibility:hidden\'>:</span>'
 
-			@refs.time.innerHTML = "#yyyymmdd<br>#hhmm"
+			this.refs.time.innerHTML = "#yyyymmdd<br>#hhmm"
 
-		@on \mount ~>
+		this.on('mount', () => {
 			@draw!
-			@clock = set-interval @draw, 1000ms
+			this.clock = set-interval @draw, 1000ms
 
-		@on \unmount ~>
+		this.on('unmount', () => {
 			clear-interval @clock
 	</script>
 </mk-ui-header-clock>
diff --git a/src/web/app/desktop/tags/ui-header-nav.tag b/src/web/app/desktop/tags/ui-header-nav.tag
index 707a9366e..8f710600f 100644
--- a/src/web/app/desktop/tags/ui-header-nav.tag
+++ b/src/web/app/desktop/tags/ui-header-nav.tag
@@ -77,37 +77,37 @@
 
 		</style>
 		<script>
-			@mixin \i
-			@mixin \api
-			@mixin \stream
+			this.mixin('i');
+			this.mixin('api');
+			this.mixin('stream');
 
-			@page = @opts.page
+			this.page = this.opts.page
 
-			@on \mount ~>
-				@stream.on \read_all_messaging_messages @on-read-all-messaging-messages
-				@stream.on \unread_messaging_message @on-unread-messaging-message
+			this.on('mount', () => {
+				@stream.on 'read_all_messaging_messages' this.on-read-all-messaging-messages
+				@stream.on 'unread_messaging_message' this.on-unread-messaging-message
 
-				# Fetch count of unread messaging messages
-				@api \messaging/unread
-				.then (count) ~>
+				// Fetch count of unread messaging messages
+				this.api 'messaging/unread' 
+				.then (count) =>
 					if count.count > 0
-						@has-unread-messaging-messages = true
-						@update!
+						this.has-unread-messaging-messages = true
+						this.update();
 
-			@on \unmount ~>
-				@stream.off \read_all_messaging_messages @on-read-all-messaging-messages
-				@stream.off \unread_messaging_message @on-unread-messaging-message
+			this.on('unmount', () => {
+				@stream.off 'read_all_messaging_messages' this.on-read-all-messaging-messages
+				@stream.off 'unread_messaging_message' this.on-unread-messaging-message
 
-			@on-read-all-messaging-messages = ~>
-				@has-unread-messaging-messages = false
-				@update!
+			on-read-all-messaging-messages() {
+				this.has-unread-messaging-messages = false
+				this.update();
 
-			@on-unread-messaging-message = ~>
-				@has-unread-messaging-messages = true
-				@update!
+			on-unread-messaging-message() {
+				this.has-unread-messaging-messages = true
+				this.update();
 
-			@messaging = ~>
-				riot.mount document.body.append-child document.create-element \mk-messaging-window
+			messaging() {
+				riot.mount document.body.appendChild document.createElement 'mk-messaging-window' 
 		</script>
 	</ul>
 </mk-ui-header-nav>
diff --git a/src/web/app/desktop/tags/ui-header-notifications.tag b/src/web/app/desktop/tags/ui-header-notifications.tag
index 65330a14e..d166df36e 100644
--- a/src/web/app/desktop/tags/ui-header-notifications.tag
+++ b/src/web/app/desktop/tags/ui-header-notifications.tag
@@ -75,31 +75,31 @@
 
 	</style>
 	<script>
-		@is-open = false
+		this.is-open = false
 
-		@toggle = ~>
+		toggle() {
 			if @is-open
 				@close!
 			else
 				@open!
 
-		@open = ~>
-			@is-open = true
-			@update!
+		open() {
+			this.is-open = true
+			this.update();
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) ~>
-				el.add-event-listener \mousedown @mousedown
+			Array.prototype.for-each.call all, (el) =>
+				el.add-event-listener 'mousedown' @mousedown
 
-		@close = ~>
-			@is-open = false
-			@update!
+		close() {
+			this.is-open = false
+			this.update();
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) ~>
-				el.remove-event-listener \mousedown @mousedown
+			Array.prototype.for-each.call all, (el) =>
+				el.remove-event-listener 'mousedown' @mousedown
 
-		@mousedown = (e) ~>
+		mousedown(e) {
 			e.prevent-default!
-			if (!contains @root, e.target) and (@root != e.target)
+			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 			return false
 
diff --git a/src/web/app/desktop/tags/ui-header-post-button.tag b/src/web/app/desktop/tags/ui-header-post-button.tag
index 071af0a15..3d391ed2e 100644
--- a/src/web/app/desktop/tags/ui-header-post-button.tag
+++ b/src/web/app/desktop/tags/ui-header-post-button.tag
@@ -35,7 +35,7 @@
 
 	</style>
 	<script>
-		@post = (e) ~>
-			@parent.parent.open-post-form!
+		post(e) {
+			this.parent.parent.open-post-form!
 	</script>
 </mk-ui-header-post-button>
diff --git a/src/web/app/desktop/tags/ui-header-search.tag b/src/web/app/desktop/tags/ui-header-search.tag
index 10ebe1da9..702c70efc 100644
--- a/src/web/app/desktop/tags/ui-header-search.tag
+++ b/src/web/app/desktop/tags/ui-header-search.tag
@@ -32,10 +32,10 @@
 
 	</style>
 	<script>
-		@mixin \page
+		this.mixin('page');
 
-		@onsubmit = (e) ~>
+		onsubmit(e) {
 			e.prevent-default!
-			@page '/search:' + @refs.q.value
+			@page '/search:' + this.refs.q.value
 	</script>
 </mk-ui-header-search>
diff --git a/src/web/app/desktop/tags/ui-header.tag b/src/web/app/desktop/tags/ui-header.tag
index 41b74181f..05d1ff665 100644
--- a/src/web/app/desktop/tags/ui-header.tag
+++ b/src/web/app/desktop/tags/ui-header.tag
@@ -81,5 +81,5 @@
 
 	</style>
 
-	<script>@mixin \i</script>
+	<script>this.mixin('i');</script>
 </mk-ui-header>
diff --git a/src/web/app/desktop/tags/ui-notification.tag b/src/web/app/desktop/tags/ui-notification.tag
index 5f8583a39..22ba98df9 100644
--- a/src/web/app/desktop/tags/ui-notification.tag
+++ b/src/web/app/desktop/tags/ui-notification.tag
@@ -22,22 +22,22 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			Velocity @root, {
-				top: \0px
+		this.on('mount', () => {
+			Velocity this.root, {
+				top: '0px' 
 			} {
 				duration: 500ms
-				easing: \ease-out
+				easing: 'ease-out' 
 			}
 
-			set-timeout ~>
-				Velocity @root, {
-					top: \-64px
+			setTimeout =>
+				Velocity this.root, {
+					top: '-64px' 
 				} {
 					duration: 500ms
-					easing: \ease-out
-					complete: ~>
-						@unmount!
+					easing: 'ease-out' 
+					complete: =>
+						this.unmount();
 				}
 			, 6000ms
 	</script>
diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag
index e40e5c88e..78bf6117c 100644
--- a/src/web/app/desktop/tags/ui.tag
+++ b/src/web/app/desktop/tags/ui.tag
@@ -12,25 +12,25 @@
 
 	</style>
 	<script>
-		@mixin \i
+		this.mixin('i');
 
-		@open-post-form = ~>
-			riot.mount document.body.append-child document.create-element \mk-post-form-window
+		open-post-form() {
+			riot.mount document.body.appendChild document.createElement 'mk-post-form-window' 
 
-		@set-root-layout = ~>
-			@root.style.padding-top = @refs.header.root.client-height + \px
+		set-root-layout() {
+			this.root.style.padding-top = this.refs.header.root.client-height + 'px' 
 
-		@on \mount ~>
+		this.on('mount', () => {
 			@set-root-layout!
-			document.add-event-listener \keydown @onkeydown
+			document.add-event-listener 'keydown' this.onkeydown
 
-		@on \unmount ~>
-			document.remove-event-listener \keydown @onkeydown
+		this.on('unmount', () => {
+			document.remove-event-listener 'keydown' this.onkeydown
 
-		@onkeydown = (e) ~>
+		onkeydown(e) {
 			tag = e.target.tag-name.to-lower-case!
-			if tag != \input and tag != \textarea
-				if e.which == 80 or e.which == 78 # p or n
+			if tag != 'input' and tag != 'textarea' 
+				if e.which == 80 or e.which == 78 // p or n
 					e.prevent-default!
 					@open-post-form!
 	</script>
diff --git a/src/web/app/desktop/tags/user-followers-window.tag b/src/web/app/desktop/tags/user-followers-window.tag
index e70682c19..a4a24d667 100644
--- a/src/web/app/desktop/tags/user-followers-window.tag
+++ b/src/web/app/desktop/tags/user-followers-window.tag
@@ -15,5 +15,5 @@
 						border-radius 4px
 
 	</style>
-	<script>@user = @opts.user</script>
+	<script>this.user = this.opts.user</script>
 </mk-user-followers-window>
diff --git a/src/web/app/desktop/tags/user-followers.tag b/src/web/app/desktop/tags/user-followers.tag
index 14f20b831..0ae29a209 100644
--- a/src/web/app/desktop/tags/user-followers.tag
+++ b/src/web/app/desktop/tags/user-followers.tag
@@ -7,12 +7,12 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@fetch = (iknow, limit, cursor, cb) ~>
-			@api \users/followers do
+		fetch(iknow, limit, cursor, cb) {
+			this.api 'users/followers' do
 				user_id: @user.id
 				iknow: iknow
 				limit: limit
diff --git a/src/web/app/desktop/tags/user-following-window.tag b/src/web/app/desktop/tags/user-following-window.tag
index 4e25e8a3c..6dbf3b05e 100644
--- a/src/web/app/desktop/tags/user-following-window.tag
+++ b/src/web/app/desktop/tags/user-following-window.tag
@@ -15,5 +15,5 @@
 						border-radius 4px
 
 	</style>
-	<script>@user = @opts.user</script>
+	<script>this.user = this.opts.user</script>
 </mk-user-following-window>
diff --git a/src/web/app/desktop/tags/user-following.tag b/src/web/app/desktop/tags/user-following.tag
index e21d391d4..f640ee7b6 100644
--- a/src/web/app/desktop/tags/user-following.tag
+++ b/src/web/app/desktop/tags/user-following.tag
@@ -7,12 +7,12 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@fetch = (iknow, limit, cursor, cb) ~>
-			@api \users/following do
+		fetch(iknow, limit, cursor, cb) {
+			this.api 'users/following' do
 				user_id: @user.id
 				iknow: iknow
 				limit: limit
diff --git a/src/web/app/desktop/tags/user-friends-graph.tag b/src/web/app/desktop/tags/user-friends-graph.tag
index ce7343494..923ea6fe9 100644
--- a/src/web/app/desktop/tags/user-friends-graph.tag
+++ b/src/web/app/desktop/tags/user-friends-graph.tag
@@ -8,57 +8,57 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
+		this.mixin('api');
+		this.mixin('is-promise');
 
-		@user = null
-		@user-promise = if @is-promise @opts.user then @opts.user else Promise.resolve @opts.user
+		this.user = null
+		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
-		@on \mount ~>
+		this.on('mount', () => {
 			user <~ @user-promise.then
-			@user = user
-			@update!
+			this.user = user
+			this.update();
 
-			@api \aggregation/users/followers do
+			this.api 'aggregation/users/followers' do
 				user_id: @user.id
 				limit: 30days
-			.then (followers) ~>
+			.then (followers) =>
 				followers = followers.reverse!
 
-				@api \aggregation/users/following do
+				this.api 'aggregation/users/following' do
 					user_id: @user.id
 					limit: 30days
-				.then (following) ~>
+				.then (following) =>
 					following = following.reverse!
 
-					new Chart @refs.canv, do
-						type: \line
+					new Chart this.refs.canv, do
+						type: 'line' 
 						data:
-							labels: following.map (x, i) ~> if i % 3 == 2 then x.date.day + '日' else ''
+							labels: following.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
 							datasets: [
 								{
-									label: \フォロー
-									data: following.map (x) ~> x.count
+									label: 'フォロー' 
+									data: following.map (x) => x.count
 									line-tension: 0
 									border-width: 2
 									fill: true
 									background-color: 'rgba(127, 221, 64, 0.2)'
-									point-background-color: \#fff
+									point-background-color: '#fff' 
 									point-radius: 4
 									point-border-width: 2
-									border-color: \#7fdd40
+									border-color: '#7fdd40' 
 								},
 								{
-									label: \フォロワー
-									data: followers.map (x) ~> x.count
+									label: 'フォロワー' 
+									data: followers.map (x) => x.count
 									line-tension: 0
 									border-width: 2
 									fill: true
 									background-color: 'rgba(255, 99, 132, 0.2)'
-									point-background-color: \#fff
+									point-background-color: '#fff' 
 									point-radius: 4
 									point-border-width: 2
-									border-color: \#FF6384
+									border-color: '#FF6384' 
 								}
 							]
 						options:
diff --git a/src/web/app/desktop/tags/user-graphs.tag b/src/web/app/desktop/tags/user-graphs.tag
index 6d49c990a..ad1c4d7ee 100644
--- a/src/web/app/desktop/tags/user-graphs.tag
+++ b/src/web/app/desktop/tags/user-graphs.tag
@@ -34,7 +34,7 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			@trigger \loaded
+		this.on('mount', () => {
+			this.trigger('loaded');
 	</script>
 </mk-user-graphs>
diff --git a/src/web/app/desktop/tags/user-header.tag b/src/web/app/desktop/tags/user-header.tag
index d49b6498b..dc7abb512 100644
--- a/src/web/app/desktop/tags/user-header.tag
+++ b/src/web/app/desktop/tags/user-header.tag
@@ -104,39 +104,39 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \update-banner
-		@mixin \NotImplementedException
+		this.mixin('i');
+		this.mixin('update-banner');
+		this.mixin('NotImplementedException');
 
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@on \mount ~>
-			window.add-event-listener \load @scroll
-			window.add-event-listener \scroll @scroll
-			window.add-event-listener \resize @scroll
+		this.on('mount', () => {
+			window.add-event-listener 'load' @scroll
+			window.add-event-listener 'scroll' @scroll
+			window.add-event-listener 'resize' @scroll
 
-		@on \unmount ~>
-			window.remove-event-listener \load @scroll
-			window.remove-event-listener \scroll @scroll
-			window.remove-event-listener \resize @scroll
+		this.on('unmount', () => {
+			window.remove-event-listener 'load' @scroll
+			window.remove-event-listener 'scroll' @scroll
+			window.remove-event-listener 'resize' @scroll
 
-		@scroll = ~>
+		scroll() {
 			top = window.scroll-y
 			height = 280px
 
 			pos = 50 - ((top / height) * 50)
-			@refs.banner.style.background-position = 'center ' + pos + '%'
+			this.refs.banner.style.background-position = 'center ' + pos + '%'
 
 			blur = top / 32
 			if blur <= 10
-				@refs.banner.style.filter = 'blur(' + blur + 'px)'
+				this.refs.banner.style.filter = 'blur(' + blur + 'px)'
 
-		@on-update-banner = ~>
+		on-update-banner() {
 			if not @SIGNIN or @I.id != @user.id
 				return
 
-			@update-banner @I, (i) ~>
+			@update-banner @I, (i) =>
 				@user.banner_url = i.banner_url
-				@update!
+				this.update();
 	</script>
 </mk-user-header>
diff --git a/src/web/app/desktop/tags/user-home.tag b/src/web/app/desktop/tags/user-home.tag
index 50fe1cbfa..db155edb1 100644
--- a/src/web/app/desktop/tags/user-home.tag
+++ b/src/web/app/desktop/tags/user-home.tag
@@ -35,10 +35,10 @@
 
 	</style>
 	<script>
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@on \mount ~>
-			@refs.tl.on \loaded ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			this.refs.tl.on('loaded', () => {
+				this.trigger('loaded');
 	</script>
 </mk-user-home>
diff --git a/src/web/app/desktop/tags/user-likes-graph.tag b/src/web/app/desktop/tags/user-likes-graph.tag
index cec80164a..099040133 100644
--- a/src/web/app/desktop/tags/user-likes-graph.tag
+++ b/src/web/app/desktop/tags/user-likes-graph.tag
@@ -8,32 +8,32 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
+		this.mixin('api');
+		this.mixin('is-promise');
 
-		@user = null
-		@user-promise = if @is-promise @opts.user then @opts.user else Promise.resolve @opts.user
+		this.user = null
+		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
-		@on \mount ~>
+		this.on('mount', () => {
 			user <~ @user-promise.then
-			@user = user
-			@update!
+			this.user = user
+			this.update();
 
-			@api \aggregation/users/like do
+			this.api 'aggregation/users/like' do
 				user_id: @user.id
 				limit: 30days
-			.then (likes) ~>
+			.then (likes) =>
 				likes = likes.reverse!
 
-				new Chart @refs.canv, do
-					type: \bar
+				new Chart this.refs.canv, do
+					type: 'bar' 
 					data:
-						labels: likes.map (x, i) ~> if i % 3 == 2 then x.date.day + '日' else ''
+						labels: likes.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
 						datasets: [
 							{
-								label: \いいねした数
-								data: likes.map (x) ~> x.count
-								background-color: \#F7796C
+								label: 'いいねした数' 
+								data: likes.map (x) => x.count
+								background-color: '#F7796C' 
 							}
 						]
 					options:
diff --git a/src/web/app/desktop/tags/user-photos.tag b/src/web/app/desktop/tags/user-photos.tag
index 3d24422de..89453b460 100644
--- a/src/web/app/desktop/tags/user-photos.tag
+++ b/src/web/app/desktop/tags/user-photos.tag
@@ -57,30 +57,30 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
+		this.mixin('api');
+		this.mixin('is-promise');
 
-		@images = []
-		@initializing = true
+		this.images = []
+		this.initializing = true
 
-		@user = null
-		@user-promise = if @is-promise @opts.user then @opts.user else Promise.resolve @opts.user
+		this.user = null
+		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
-		@on \mount ~>
-			@user-promise.then (user) ~>
-				@user = user
-				@update!
+		this.on('mount', () => {
+			@user-promise.then (user) =>
+				this.user = user
+				this.update();
 
-				@api \users/posts do
+				this.api 'users/posts' do
 					user_id: @user.id
 					with_media: true
 					limit: 9posts
-				.then (posts) ~>
-					@initializing = false
-					posts.for-each (post) ~>
-						post.media.for-each (image) ~>
+				.then (posts) =>
+					this.initializing = false
+					posts.for-each (post) =>
+						post.media.for-each (image) =>
 							if @images.length < 9
 								@images.push image
-					@update!
+					this.update();
 	</script>
 </mk-user-photos>
diff --git a/src/web/app/desktop/tags/user-posts-graph.tag b/src/web/app/desktop/tags/user-posts-graph.tag
index dacfd6132..0efc61310 100644
--- a/src/web/app/desktop/tags/user-posts-graph.tag
+++ b/src/web/app/desktop/tags/user-posts-graph.tag
@@ -8,50 +8,50 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
+		this.mixin('api');
+		this.mixin('is-promise');
 
-		@user = null
-		@user-promise = if @is-promise @opts.user then @opts.user else Promise.resolve @opts.user
+		this.user = null
+		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
-		@on \mount ~>
+		this.on('mount', () => {
 			user <~ @user-promise.then
-			@user = user
-			@update!
+			this.user = user
+			this.update();
 
-			@api \aggregation/users/post do
+			this.api 'aggregation/users/post' do
 				user_id: @user.id
 				limit: 30days
-			.then (data) ~>
+			.then (data) =>
 				data = data.reverse!
-				new Chart @refs.canv, do
-					type: \line
+				new Chart this.refs.canv, do
+					type: 'line' 
 					data:
-						labels: data.map (x, i) ~> if i % 3 == 2 then x.date.day + '日' else ''
+						labels: data.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
 						datasets: [
 							{
-								label: \投稿
-								data: data.map (x) ~> x.posts
+								label: '投稿' 
+								data: data.map (x) => x.posts
 								line-tension: 0
 								point-radius: 0
-								background-color: \#555
-								border-color: \transparent
+								background-color: '#555' 
+								border-color: 'transparent' 
 							},
 							{
-								label: \Repost
-								data: data.map (x) ~> x.reposts
+								label: 'Repost' 
+								data: data.map (x) => x.reposts
 								line-tension: 0
 								point-radius: 0
-								background-color: \#a2d61e
-								border-color: \transparent
+								background-color: '#a2d61e' 
+								border-color: 'transparent' 
 							},
 							{
-								label: \返信
-								data: data.map (x) ~> x.replies
+								label: '返信' 
+								data: data.map (x) => x.replies
 								line-tension: 0
 								point-radius: 0
-								background-color: \#F7796C
-								border-color: \transparent
+								background-color: '#F7796C' 
+								border-color: 'transparent' 
 							}
 						]
 					options:
diff --git a/src/web/app/desktop/tags/user-preview.tag b/src/web/app/desktop/tags/user-preview.tag
index 7d140c095..d17f7557d 100644
--- a/src/web/app/desktop/tags/user-preview.tag
+++ b/src/web/app/desktop/tags/user-preview.tag
@@ -97,47 +97,47 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \api
+		this.mixin('i');
+		this.mixin('api');
 
-		@u = @opts.user
-		@user = null
-		@user-promise =
-			if typeof @u == \string
-				new Promise (resolve, reject) ~>
-					@api \users/show do
-						user_id: if @u.0 == \@ then undefined else @u
-						username: if @u.0 == \@ then @u.substr 1 else undefined
-					.then (user) ~>
+		this.u = this.opts.user
+		this.user = null
+		this.user-promise = 
+			if typeof @u == 'string' 
+				new Promise (resolve, reject) =>
+					this.api 'users/show' do
+						user_id: if @u.0 == '@' then undefined else @u
+						username: if @u.0 == '@' then @u.substr 1 else undefined
+					.then (user) =>
 						resolve user
 			else
 				Promise.resolve @u
 
-		@on \mount ~>
-			@user-promise.then (user) ~>
-				@user = user
-				@update!
+		this.on('mount', () => {
+			@user-promise.then (user) =>
+				this.user = user
+				this.update();
 
-			Velocity @root, {
+			Velocity this.root, {
 				opacity: 0
-				'margin-top': \-8px
+				'margin-top': '-8px' 
 			} 0ms
-			Velocity @root, {
+			Velocity this.root, {
 				opacity: 1
 				'margin-top': 0
 			} {
 				duration: 200ms
-				easing: \ease-out
+				easing: 'ease-out' 
 			}
 
-		@close = ~>
-			Velocity @root, {
+		close() {
+			Velocity this.root, {
 				opacity: 0
-				'margin-top': \-8px
+				'margin-top': '-8px' 
 			} {
 				duration: 200ms
-				easing: \ease-out
-				complete: ~> @unmount!
+				easing: 'ease-out' 
+				complete: => this.unmount();
 			}
 	</script>
 </mk-user-preview>
diff --git a/src/web/app/desktop/tags/user-profile.tag b/src/web/app/desktop/tags/user-profile.tag
index d8984e971..a94f50c7b 100644
--- a/src/web/app/desktop/tags/user-profile.tag
+++ b/src/web/app/desktop/tags/user-profile.tag
@@ -80,19 +80,19 @@
 
 	</style>
 	<script>
-		@age = require \s-age
+		this.age = require 's-age' 
 
-		@mixin \i
+		this.mixin('i');
 
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@show-following = ~>
-			window = document.body.append-child document.create-element \mk-user-following-window
+		show-following() {
+			window = document.body.appendChild document.createElement 'mk-user-following-window' 
 			riot.mount window, do
 				user: @user
 
-		@show-followers = ~>
-			window = document.body.append-child document.create-element \mk-user-followers-window
+		show-followers() {
+			window = document.body.appendChild document.createElement 'mk-user-followers-window' 
 			riot.mount window, do
 				user: @user
 	</script>
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index b0ed542a4..b8e39b730 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -46,91 +46,91 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
-		@mixin \get-post-summary
+		this.mixin('api');
+		this.mixin('is-promise');
+		this.mixin('get-post-summary');
 
-		@user = null
-		@user-promise = if @is-promise @opts.user then @opts.user else Promise.resolve @opts.user
-		@is-loading = true
-		@is-empty = false
-		@more-loading = false
-		@unread-count = 0
-		@mode = \default
+		this.user = null
+		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
+		this.is-loading = true
+		this.is-empty = false
+		this.more-loading = false
+		this.unread-count = 0
+		this.mode = 'default' 
 
-		@on \mount ~>
-			document.add-event-listener \visibilitychange @window-on-visibilitychange, false
-			document.add-event-listener \keydown @on-document-keydown
-			window.add-event-listener \scroll @on-scroll
+		this.on('mount', () => {
+			document.add-event-listener 'visibilitychange' @window-on-visibilitychange, false
+			document.add-event-listener 'keydown' this.on-document-keydown
+			window.add-event-listener 'scroll' this.on-scroll
 
-			@user-promise.then (user) ~>
-				@user = user
-				@update!
+			@user-promise.then (user) =>
+				this.user = user
+				this.update();
 
-				@fetch ~>
-					@trigger \loaded
+				@fetch =>
+					this.trigger('loaded');
 
-		@on \unmount ~>
-			document.remove-event-listener \visibilitychange @window-on-visibilitychange
-			document.remove-event-listener \keydown @on-document-keydown
-			window.remove-event-listener \scroll @on-scroll
+		this.on('unmount', () => {
+			document.remove-event-listener 'visibilitychange' @window-on-visibilitychange
+			document.remove-event-listener 'keydown' this.on-document-keydown
+			window.remove-event-listener 'scroll' this.on-scroll
 
-		@on-document-keydown = (e) ~>
+		on-document-keydown(e) {
 			tag = e.target.tag-name.to-lower-case!
-			if tag != \input and tag != \textarea
-				if e.which == 84 # t
-					@refs.timeline.focus!
+			if tag != 'input' and tag != 'textarea' 
+				if e.which == 84 // t
+					this.refs.timeline.focus();
 
-		@fetch = (cb) ~>
-			@api \users/posts do
+		fetch(cb) {
+			this.api 'users/posts' do
 				user_id: @user.id
-				with_replies: @mode == \with-replies
-			.then (posts) ~>
-				@is-loading = false
-				@is-empty = posts.length == 0
-				@update!
-				@refs.timeline.set-posts posts
+				with_replies: @mode == 'with-replies' 
+			.then (posts) =>
+				this.is-loading = false
+				this.is-empty = posts.length == 0
+				this.update();
+				this.refs.timeline.set-posts posts
 				if cb? then cb!
-			.catch (err) ~>
+			.catch (err) =>
 				console.error err
 				if cb? then cb!
 
-		@more = ~>
-			if @more-loading or @is-loading or @refs.timeline.posts.length == 0
+		more() {
+			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
 				return
-			@more-loading = true
-			@update!
-			@api \users/posts do
+			this.more-loading = true
+			this.update();
+			this.api 'users/posts' do
 				user_id: @user.id
-				with_replies: @mode == \with-replies
-				max_id: @refs.timeline.tail!.id
-			.then (posts) ~>
-				@more-loading = false
-				@update!
-				@refs.timeline.prepend-posts posts
-			.catch (err) ~>
+				with_replies: @mode == 'with-replies' 
+				max_id: this.refs.timeline.tail!.id
+			.then (posts) =>
+				this.more-loading = false
+				this.update();
+				this.refs.timeline.prepend-posts posts
+			.catch (err) =>
 				console.error err
 
-		@on-stream-post = (post) ~>
-			@is-empty = false
-			@update!
-			@refs.timeline.add-post post
+		on-stream-post(post) {
+			this.is-empty = false
+			this.update();
+			this.refs.timeline.add-post post
 
 			if document.hidden
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
-		@window-on-visibilitychange = ~>
+		window-on-visibilitychange() {
 			if !document.hidden
-				@unread-count = 0
+				this.unread-count = 0
 				document.title = 'Misskey'
 
-		@on-scroll = ~>
+		on-scroll() {
 			current = window.scroll-y + window.inner-height
-			if current > document.body.offset-height - 16 # 遊び
+			if current > document.body.offset-height - 16 // 遊び
 				@more!
 
-		@set-mode = (mode) ~>
+		set-mode(mode) {
 			@update do
 				mode: mode
 			@fetch!
diff --git a/src/web/app/desktop/tags/user.tag b/src/web/app/desktop/tags/user.tag
index 24f2e958a..8e151c831 100644
--- a/src/web/app/desktop/tags/user.tag
+++ b/src/web/app/desktop/tags/user.tag
@@ -32,20 +32,20 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@username = @opts.user
-		@page = if @opts.page? then @opts.page else \home
-		@fetching = true
-		@user = null
+		this.username = this.opts.user
+		this.page = if this.opts.page? then this.opts.page else 'home' 
+		this.fetching = true
+		this.user = null
 
-		@on \mount ~>
-			@api \users/show do
+		this.on('mount', () => {
+			this.api 'users/show' do
 				username: @username
-			.then (user) ~>
-				@fetching = false
-				@user = user
-				@update!
-				@trigger \loaded
+			.then (user) =>
+				this.fetching = false
+				this.user = user
+				this.update();
+				this.trigger('loaded');
 	</script>
 </mk-user>
diff --git a/src/web/app/desktop/tags/users-list.tag b/src/web/app/desktop/tags/users-list.tag
index 51edd2ee3..af0f35d63 100644
--- a/src/web/app/desktop/tags/users-list.tag
+++ b/src/web/app/desktop/tags/users-list.tag
@@ -88,44 +88,44 @@
 
 	</style>
 	<script>
-		@mixin \i
+		this.mixin('i');
 
-		@limit = 30users
-		@mode = \all
+		this.limit = 30users
+		this.mode = 'all' 
 
-		@fetching = true
-		@more-fetching = false
+		this.fetching = true
+		this.more-fetching = false
 
-		@on \mount ~>
-			@fetch ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			@fetch =>
+				this.trigger('loaded');
 
-		@fetch = (cb) ~>
-			@fetching = true
-			@update!
-			obj <~ @opts.fetch do
-				@mode == \iknow
+		fetch(cb) {
+			this.fetching = true
+			this.update();
+			obj <~ this.opts.fetch do
+				@mode == 'iknow' 
 				@limit
 				null
-			@users = obj.users
-			@next = obj.next
-			@fetching = false
-			@update!
+			this.users = obj.users
+			this.next = obj.next
+			this.fetching = false
+			this.update();
 			if cb? then cb!
 
-		@more = ~>
-			@more-fetching = true
-			@update!
-			obj <~ @opts.fetch do
-				@mode == \iknow
+		more() {
+			this.more-fetching = true
+			this.update();
+			obj <~ this.opts.fetch do
+				@mode == 'iknow' 
 				@limit
 				@cursor
-			@users = @users.concat obj.users
-			@next = obj.next
-			@more-fetching = false
-			@update!
+			this.users = @users.concat obj.users
+			this.next = obj.next
+			this.more-fetching = false
+			this.update();
 
-		@set-mode = (mode) ~>
+		set-mode(mode) {
 			@update do
 				mode: mode
 
diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index 323c294c2..f3d8ff7be 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -192,101 +192,101 @@
 
 	</style>
 	<script>
-		@min-height = 40px
-		@min-width = 200px
+		this.min-height = 40px
+		this.min-width = 200px
 
-		@is-modal = if @opts.is-modal? then @opts.is-modal else false
-		@can-close = if @opts.can-close? then @opts.can-close else true
-		@is-flexible = !@opts.height?
-		@can-resize = not @is-flexible
+		this.is-modal = if this.opts.is-modal? then this.opts.is-modal else false
+		this.can-close = if this.opts.can-close? then this.opts.can-close else true
+		this.is-flexible = !this.opts.height?
+		this.can-resize = not @is-flexible
 
-		@on \mount ~>
-			@refs.main.style.width = @opts.width || \530px
-			@refs.main.style.height = @opts.height || \auto
+		this.on('mount', () => {
+			this.refs.main.style.width = this.opts.width || '530px' 
+			this.refs.main.style.height = this.opts.height || 'auto' 
 
-			@refs.main.style.top = \15%
-			@refs.main.style.left = (window.inner-width / 2) - (@refs.main.offset-width / 2) + \px
+			this.refs.main.style.top = '15%' 
+			this.refs.main.style.left = (window.inner-width / 2) - (this.refs.main.offset-width / 2) + 'px' 
 
-			@refs.header.add-event-listener \contextmenu (e) ~>
+			this.refs.header.add-event-listener 'contextmenu' (e) =>
 				e.prevent-default!
 
-			window.add-event-listener \resize @on-browser-resize
+			window.add-event-listener 'resize' this.on-browser-resize
 
 			@open!
 
-		@on \unmount ~>
-			window.remove-event-listener \resize @on-browser-resize
+		this.on('unmount', () => {
+			window.remove-event-listener 'resize' this.on-browser-resize
 
-		@on-browser-resize = ~>
-			position = @refs.main.get-bounding-client-rect!
+		on-browser-resize() {
+			position = this.refs.main.get-bounding-client-rect!
 			browser-width = window.inner-width
 			browser-height = window.inner-height
-			window-width = @refs.main.offset-width
-			window-height = @refs.main.offset-height
+			window-width = this.refs.main.offset-width
+			window-height = this.refs.main.offset-height
 
 			if position.left < 0
-				@refs.main.style.left = 0
+				this.refs.main.style.left = 0
 
 			if position.top < 0
-				@refs.main.style.top = 0
+				this.refs.main.style.top = 0
 
 			if position.left + window-width > browser-width
-				@refs.main.style.left = browser-width - window-width + \px
+				this.refs.main.style.left = browser-width - window-width + 'px' 
 
 			if position.top + window-height > browser-height
-				@refs.main.style.top = browser-height - window-height + \px
+				this.refs.main.style.top = browser-height - window-height + 'px' 
 
-		@open = ~>
-			@trigger \opening
+		open() {
+			this.trigger('opening');
 
 			@top!
 
 			if @is-modal
-				@refs.bg.style.pointer-events = \auto
-				Velocity @refs.bg, \finish true
-				Velocity @refs.bg, {
+				this.refs.bg.style.pointer-events = 'auto' 
+				Velocity this.refs.bg, 'finish' true
+				Velocity this.refs.bg, {
 					opacity: 1
 				} {
 					queue: false
 					duration: 100ms
-					easing: \linear
+					easing: 'linear' 
 				}
 
-			@refs.main.style.pointer-events = \auto
-			Velocity @refs.main, \finish true
-			Velocity @refs.main, {scale: 1.1} 0ms
-			Velocity @refs.main, {
+			this.refs.main.style.pointer-events = 'auto' 
+			Velocity this.refs.main, 'finish' true
+			Velocity this.refs.main, {scale: 1.1} 0ms
+			Velocity this.refs.main, {
 				opacity: 1
 				scale: 1
 			} {
 				queue: false
 				duration: 200ms
-				easing: \ease-out
+				easing: 'ease-out' 
 			}
 
-			#@refs.main.focus!
+			#this.refs.main.focus();
 
-			set-timeout ~>
-				@trigger \opened
+			setTimeout =>
+				this.trigger('opened');
 			, 300ms
 
-		@close = ~>
-			@trigger \closing
+		close() {
+			this.trigger('closing');
 
 			if @is-modal
-				@refs.bg.style.pointer-events = \none
-				Velocity @refs.bg, \finish true
-				Velocity @refs.bg, {
+				this.refs.bg.style.pointer-events = 'none' 
+				Velocity this.refs.bg, 'finish' true
+				Velocity this.refs.bg, {
 					opacity: 0
 				} {
 					queue: false
 					duration: 300ms
-					easing: \linear
+					easing: 'linear' 
 				}
 
-			@refs.main.style.pointer-events = \none
-			Velocity @refs.main, \finish true
-			Velocity @refs.main, {
+			this.refs.main.style.pointer-events = 'none' 
+			Velocity this.refs.main, 'finish' true
+			Velocity this.refs.main, {
 				opacity: 0
 				scale: 0.8
 			} {
@@ -295,45 +295,45 @@
 				easing: [ 0.5, -0.5, 1, 0.5 ]
 			}
 
-			set-timeout ~>
-				@trigger \closed
+			setTimeout =>
+				this.trigger('closed');
 			, 300ms
 
-		# 最前面へ移動します
-		@top = ~>
+		// 最前面へ移動します
+		top() {
 			z = 0
 
-			ws = document.query-selector-all \mk-window
-			ws.for-each (w) !~>
-				if w == @root then return
+			ws = document.query-selector-all 'mk-window' 
+			ws.for-each (w) !=>
+				if w == this.root then return
 				m = w.query-selector ':scope > .main'
 				mz = Number(document.default-view.get-computed-style m, null .z-index)
 				if mz > z then z := mz
 
 			if z > 0
-				@refs.main.style.z-index = z + 1
-				if @is-modal then @refs.bg.style.z-index = z + 1
+				this.refs.main.style.z-index = z + 1
+				if @is-modal then this.refs.bg.style.z-index = z + 1
 
-		@repel-move = (e) ~>
+		repel-move(e) {
 			e.stop-propagation!
 			return true
 
-		@bg-click = ~>
+		bg-click() {
 			if @can-close
 				@close!
 
-		@on-body-mousedown = (e) ~>
+		on-body-mousedown(e) {
 			@top!
 			true
 
-		# ヘッダー掴み時
-		@on-header-mousedown = (e) ~>
+		// ヘッダー掴み時
+		on-header-mousedown(e) {
 			e.prevent-default!
 
-			if not contains @refs.main, document.active-element
-				@refs.main.focus!
+			if not contains this.refs.main, document.active-element
+				this.refs.main.focus();
 
-			position = @refs.main.get-bounding-client-rect!
+			position = this.refs.main.get-bounding-client-rect!
 
 			click-x = e.client-x
 			click-y = e.client-y
@@ -341,168 +341,168 @@
 			move-base-y = click-y - position.top
 			browser-width = window.inner-width
 			browser-height = window.inner-height
-			window-width = @refs.main.offset-width
-			window-height = @refs.main.offset-height
+			window-width = this.refs.main.offset-width
+			window-height = this.refs.main.offset-height
 
-			# 動かした時
-			drag-listen (me) ~>
+			// 動かした時
+			drag-listen (me) =>
 				move-left = me.client-x - move-base-x
 				move-top = me.client-y - move-base-y
 
-				# 上はみ出し
+				// 上はみ出し
 				if move-top < 0
 					move-top = 0
 
-				# 左はみ出し
+				// 左はみ出し
 				if move-left < 0
 					move-left = 0
 
-				# 下はみ出し
+				// 下はみ出し
 				if move-top + window-height > browser-height
 					move-top = browser-height - window-height
 
-				# 右はみ出し
+				// 右はみ出し
 				if move-left + window-width > browser-width
 					move-left = browser-width - window-width
 
-				@refs.main.style.left = move-left + \px
-				@refs.main.style.top = move-top + \px
+				this.refs.main.style.left = move-left + 'px' 
+				this.refs.main.style.top = move-top + 'px' 
 
-		# 上ハンドル掴み時
-		@on-top-handle-mousedown = (e) ~>
+		// 上ハンドル掴み時
+		on-top-handle-mousedown(e) {
 			e.prevent-default!
 
 			base = e.client-y
-			height = parse-int((get-computed-style @refs.main, '').height, 10)
-			top = parse-int((get-computed-style @refs.main, '').top, 10)
+			height = parse-int((get-computed-style this.refs.main, '').height, 10)
+			top = parse-int((get-computed-style this.refs.main, '').top, 10)
 
-			# 動かした時
-			drag-listen (me) ~>
+			// 動かした時
+			drag-listen (me) =>
 				move = me.client-y - base
 				if top + move > 0
 					if height + -move > @min-height
 						@apply-transform-height height + -move
 						@apply-transform-top top + move
-					else # 最小の高さより小さくなろうとした時
+					else // 最小の高さより小さくなろうとした時
 						@apply-transform-height @min-height
 						@apply-transform-top top + (height - @min-height)
-				else # 上のはみ出し時
+				else // 上のはみ出し時
 					@apply-transform-height top + height
 					@apply-transform-top 0
 
-		# 右ハンドル掴み時
-		@on-right-handle-mousedown = (e) ~>
+		// 右ハンドル掴み時
+		on-right-handle-mousedown(e) {
 			e.prevent-default!
 
 			base = e.client-x
-			width = parse-int((get-computed-style @refs.main, '').width, 10)
-			left = parse-int((get-computed-style @refs.main, '').left, 10)
+			width = parse-int((get-computed-style this.refs.main, '').width, 10)
+			left = parse-int((get-computed-style this.refs.main, '').left, 10)
 			browser-width = window.inner-width
 
-			# 動かした時
-			drag-listen (me) ~>
+			// 動かした時
+			drag-listen (me) =>
 				move = me.client-x - base
 				if left + width + move < browser-width
 					if width + move > @min-width
 						@apply-transform-width width + move
-					else # 最小の幅より小さくなろうとした時
+					else // 最小の幅より小さくなろうとした時
 						@apply-transform-width @min-width
-				else # 右のはみ出し時
+				else // 右のはみ出し時
 					@apply-transform-width browser-width - left
 
-		# 下ハンドル掴み時
-		@on-bottom-handle-mousedown = (e) ~>
+		// 下ハンドル掴み時
+		on-bottom-handle-mousedown(e) {
 			e.prevent-default!
 
 			base = e.client-y
-			height = parse-int((get-computed-style @refs.main, '').height, 10)
-			top = parse-int((get-computed-style @refs.main, '').top, 10)
+			height = parse-int((get-computed-style this.refs.main, '').height, 10)
+			top = parse-int((get-computed-style this.refs.main, '').top, 10)
 			browser-height = window.inner-height
 
-			# 動かした時
-			drag-listen (me) ~>
+			// 動かした時
+			drag-listen (me) =>
 				move = me.client-y - base
 				if top + height + move < browser-height
 					if height + move > @min-height
 						@apply-transform-height height + move
-					else # 最小の高さより小さくなろうとした時
+					else // 最小の高さより小さくなろうとした時
 						@apply-transform-height @min-height
-				else # 下のはみ出し時
+				else // 下のはみ出し時
 					@apply-transform-height browser-height - top
 
-		# 左ハンドル掴み時
-		@on-left-handle-mousedown = (e) ~>
+		// 左ハンドル掴み時
+		on-left-handle-mousedown(e) {
 			e.prevent-default!
 
 			base = e.client-x
-			width = parse-int((get-computed-style @refs.main, '').width, 10)
-			left = parse-int((get-computed-style @refs.main, '').left, 10)
+			width = parse-int((get-computed-style this.refs.main, '').width, 10)
+			left = parse-int((get-computed-style this.refs.main, '').left, 10)
 
-			# 動かした時
-			drag-listen (me) ~>
+			// 動かした時
+			drag-listen (me) =>
 				move = me.client-x - base
 				if left + move > 0
 					if width + -move > @min-width
 						@apply-transform-width width + -move
 						@apply-transform-left left + move
-					else # 最小の幅より小さくなろうとした時
+					else // 最小の幅より小さくなろうとした時
 						@apply-transform-width @min-width
 						@apply-transform-left left + (width - @min-width)
-				else # 左のはみ出し時
+				else // 左のはみ出し時
 					@apply-transform-width left + width
 					@apply-transform-left 0
 
-		# 左上ハンドル掴み時
-		@on-top-left-handle-mousedown = (e) ~>
-			@on-top-handle-mousedown e
-			@on-left-handle-mousedown e
+		// 左上ハンドル掴み時
+		on-top-left-handle-mousedown(e) {
+			this.on-top-handle-mousedown e
+			this.on-left-handle-mousedown e
 
-		# 右上ハンドル掴み時
-		@on-top-right-handle-mousedown = (e) ~>
-			@on-top-handle-mousedown e
-			@on-right-handle-mousedown e
+		// 右上ハンドル掴み時
+		on-top-right-handle-mousedown(e) {
+			this.on-top-handle-mousedown e
+			this.on-right-handle-mousedown e
 
-		# 右下ハンドル掴み時
-		@on-bottom-right-handle-mousedown = (e) ~>
-			@on-bottom-handle-mousedown e
-			@on-right-handle-mousedown e
+		// 右下ハンドル掴み時
+		on-bottom-right-handle-mousedown(e) {
+			this.on-bottom-handle-mousedown e
+			this.on-right-handle-mousedown e
 
-		# 左下ハンドル掴み時
-		@on-bottom-left-handle-mousedown = (e) ~>
-			@on-bottom-handle-mousedown e
-			@on-left-handle-mousedown e
+		// 左下ハンドル掴み時
+		on-bottom-left-handle-mousedown(e) {
+			this.on-bottom-handle-mousedown e
+			this.on-left-handle-mousedown e
 
-		# 高さを適用
-		@apply-transform-height = (height) ~>
-			@refs.main.style.height = height + \px
+		// 高さを適用
+		apply-transform-height(height) {
+			this.refs.main.style.height = height + 'px' 
 
-		# 幅を適用
-		@apply-transform-width = (width) ~>
-			@refs.main.style.width = width + \px
+		// 幅を適用
+		apply-transform-width(width) {
+			this.refs.main.style.width = width + 'px' 
 
-		# Y座標を適用
-		@apply-transform-top = (top) ~>
-			@refs.main.style.top = top + \px
+		// Y座標を適用
+		apply-transform-top(top) {
+			this.refs.main.style.top = top + 'px' 
 
-		# X座標を適用
-		@apply-transform-left = (left) ~>
-			@refs.main.style.left = left + \px
+		// X座標を適用
+		apply-transform-left(left) {
+			this.refs.main.style.left = left + 'px' 
 
 		function drag-listen fn
-			window.add-event-listener \mousemove  fn
-			window.add-event-listener \mouseleave drag-clear.bind null fn
-			window.add-event-listener \mouseup    drag-clear.bind null fn
+			window.add-event-listener 'mousemove'  fn
+			window.add-event-listener 'mouseleave' drag-clear.bind null fn
+			window.add-event-listener 'mouseup'    drag-clear.bind null fn
 
 		function drag-clear fn
-			window.remove-event-listener \mousemove  fn
-			window.remove-event-listener \mouseleave drag-clear
-			window.remove-event-listener \mouseup    drag-clear
+			window.remove-event-listener 'mousemove'  fn
+			window.remove-event-listener 'mouseleave' drag-clear
+			window.remove-event-listener 'mouseup'    drag-clear
 
-		@ondragover = (e) ~>
-			e.data-transfer.drop-effect = \none
+		ondragover(e) {
+			e.data-transfer.drop-effect = 'none' 
 
-		@on-keydown = (e) ~>
-			if e.which == 27 # Esc
+		on-keydown(e) {
+			if e.which == 27 // Esc
 				if @can-close
 					e.prevent-default!
 					e.stop-propagation!
diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag
index 86e694e94..a298d5ce0 100644
--- a/src/web/app/dev/tags/new-app-form.tag
+++ b/src/web/app/dev/tags/new-app-form.tag
@@ -178,64 +178,64 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@nid-state = null
+		this.nid-state = null
 
-		@on-change-nid = ~>
-			nid = @refs.nid.value
+		on-change-nid() {
+			nid = this.refs.nid.value
 
 			if nid == ''
-				@nid-state = null
-				@update!
+				this.nid-state = null
+				this.update();
 				return
 
 			err = switch
-				| not nid.match /^[a-zA-Z0-9\-]+$/ => \invalid-format
-				| nid.length < 3chars              => \min-range
-				| nid.length > 30chars             => \max-range
+				| not nid.match /^[a-zA-Z0-9\-]+$/ => 'invalid-format' 
+				| nid.length < 3chars              => 'min-range' 
+				| nid.length > 30chars             => 'max-range' 
 				| _                                     => null
 
 			if err?
-				@nid-state = err
-				@update!
+				this.nid-state = err
+				this.update();
 			else
-				@nid-state = \wait
-				@update!
+				this.nid-state = 'wait' 
+				this.update();
 
-				@api \app/name_id/available do
+				this.api 'app/name_id/available' do
 					name_id: nid
-				.then (result) ~>
+				.then (result) =>
 					if result.available
-						@nid-state = \ok
+						this.nid-state = 'ok' 
 					else
-						@nid-state = \unavailable
-					@update!
-				.catch (err) ~>
-					@nid-state = \error
-					@update!
+						this.nid-state = 'unavailable' 
+					this.update();
+				.catch (err) =>
+					this.nid-state = 'error' 
+					this.update();
 
-		@onsubmit = ~>
-			name = @refs.name.value
-			nid = @refs.nid.value
-			description = @refs.description.value
-			cb = @refs.cb.value
+		onsubmit() {
+			name = this.refs.name.value
+			nid = this.refs.nid.value
+			description = this.refs.description.value
+			cb = this.refs.cb.value
 			permission = []
 
-			@refs.permission.query-selector-all \input .for-each (el) ~>
+			this.refs.permission.query-selector-all 'input' .for-each (el) =>
 				if el.checked then permission.push el.value
 
-			locker = document.body.append-child document.create-element \mk-locker
+			locker = document.body.appendChild document.createElement 'mk-locker' 
 
-			@api \app/create do
+			this.api 'app/create' do
 				name: name
 				name_id: nid
 				description: description
 				callback_url: cb
-				permission: permission.join \,
-			.then ~>
+				permission: permission.join ',' 
+			.then =>
 				location.href = '/apps'
-			.catch ~>
+			.catch =>
 				alert 'アプリの作成に失敗しました。再度お試しください。'
 
 				locker.parent-node.remove-child locker
diff --git a/src/web/app/dev/tags/pages/app.tag b/src/web/app/dev/tags/pages/app.tag
index 7eaf9decf..3512dd747 100644
--- a/src/web/app/dev/tags/pages/app.tag
+++ b/src/web/app/dev/tags/pages/app.tag
@@ -15,16 +15,16 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@fetching = true
+		this.fetching = true
 
-		@on \mount ~>
-			@api \app/show do
-				app_id: @opts.app
-			.then (app) ~>
-				@app = app
-				@fetching = false
-				@update!
+		this.on('mount', () => {
+			this.api 'app/show' do
+				app_id: this.opts.app
+			.then (app) =>
+				this.app = app
+				this.fetching = false
+				this.update();
 	</script>
 </mk-app-page>
diff --git a/src/web/app/dev/tags/pages/apps.tag b/src/web/app/dev/tags/pages/apps.tag
index 03806c6da..58e09e24e 100644
--- a/src/web/app/dev/tags/pages/apps.tag
+++ b/src/web/app/dev/tags/pages/apps.tag
@@ -16,15 +16,15 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@fetching = true
+		this.fetching = true
 
-		@on \mount ~>
-			@api \my/apps
-			.then (apps) ~>
-				@fetching = false
-				@apps = apps
-				@update!
+		this.on('mount', () => {
+			this.api 'my/apps' 
+			.then (apps) =>
+				this.fetching = false
+				this.apps = apps
+				this.update();
 	</script>
 </mk-apps-page>
diff --git a/src/web/app/mobile/tags/drive-selector.tag b/src/web/app/mobile/tags/drive-selector.tag
index 7039ac26a..d1ecc29b5 100644
--- a/src/web/app/mobile/tags/drive-selector.tag
+++ b/src/web/app/mobile/tags/drive-selector.tag
@@ -56,19 +56,19 @@
 
 	</style>
 	<script>
-		@files = []
+		this.files = []
 
-		@on \mount ~>
-			@refs.browser.on \change-selected (files) ~>
-				@files = files
-				@update!
+		this.on('mount', () => {
+			this.refs.browser.on('change-selected', (files) => {
+				this.files = files
+				this.update();
 
-		@cancel = ~>
-			@trigger \canceled
-			@unmount!
+		cancel() {
+			this.trigger('canceled');
+			this.unmount();
 
-		@ok = ~>
-			@trigger \selected @files
-			@unmount!
+		ok() {
+			this.trigger 'selected' @files
+			this.unmount();
 	</script>
 </mk-drive-selector>
diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag
index 06ed54e76..f7fc07f00 100644
--- a/src/web/app/mobile/tags/drive.tag
+++ b/src/web/app/mobile/tags/drive.tag
@@ -128,91 +128,91 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \stream
+		this.mixin('api');
+		this.mixin('stream');
 
-		@files = []
-		@folders = []
-		@hierarchy-folders = []
-		@selected-files = []
+		this.files = []
+		this.folders = []
+		this.hierarchy-folders = []
+		this.selected-files = []
 
-		# 現在の階層(フォルダ)
-		# * null でルートを表す
-		@folder = null
+		// 現在の階層(フォルダ)
+		// * null でルートを表す
+		this.folder = null
 
-		@file = null
+		this.file = null
 
-		@is-select-mode = @opts.select? and @opts.select
-		@multiple = if @opts.multiple? then @opts.multiple else false
+		this.is-select-mode = this.opts.select? and this.opts.select
+		this.multiple = if this.opts.multiple? then this.opts.multiple else false
 
-		@on \mount ~>
-			@stream.on \drive_file_created @on-stream-drive-file-created
-			@stream.on \drive_file_updated @on-stream-drive-file-updated
-			@stream.on \drive_folder_created @on-stream-drive-folder-created
-			@stream.on \drive_folder_updated @on-stream-drive-folder-updated
+		this.on('mount', () => {
+			@stream.on 'drive_file_created' this.on-stream-drive-file-created
+			@stream.on 'drive_file_updated' this.on-stream-drive-file-updated
+			@stream.on 'drive_folder_created' this.on-stream-drive-folder-created
+			@stream.on 'drive_folder_updated' this.on-stream-drive-folder-updated
 
-			# Riotのバグでnullを渡しても""になる
-			# https://github.com/riot/riot/issues/2080
-			#if @opts.folder?
-			if @opts.folder? and @opts.folder != ''
-				@cd @opts.folder, true
-			else if @opts.file? and @opts.file != ''
-				@cf @opts.file, true
+			// Riotのバグでnullを渡しても""になる
+			// https://github.com/riot/riot/issues/2080
+			#if this.opts.folder?
+			if this.opts.folder? and this.opts.folder != ''
+				@cd this.opts.folder, true
+			else if this.opts.file? and this.opts.file != ''
+				@cf this.opts.file, true
 			else
 				@load!
 
-		@on \unmount ~>
-			@stream.off \drive_file_created @on-stream-drive-file-created
-			@stream.off \drive_file_updated @on-stream-drive-file-updated
-			@stream.off \drive_folder_created @on-stream-drive-folder-created
-			@stream.off \drive_folder_updated @on-stream-drive-folder-updated
+		this.on('unmount', () => {
+			@stream.off 'drive_file_created' this.on-stream-drive-file-created
+			@stream.off 'drive_file_updated' this.on-stream-drive-file-updated
+			@stream.off 'drive_folder_created' this.on-stream-drive-folder-created
+			@stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
 
-		@on-stream-drive-file-created = (file) ~>
+		on-stream-drive-file-created(file) {
 			@add-file file, true
 
-		@on-stream-drive-file-updated = (file) ~>
+		on-stream-drive-file-updated(file) {
 			current = if @folder? then @folder.id else null
 			if current != file.folder_id
 				@remove-file file
 			else
 				@add-file file, true
 
-		@on-stream-drive-folder-created = (folder) ~>
+		on-stream-drive-folder-created(folder) {
 			@add-folder folder, true
 
-		@on-stream-drive-folder-updated = (folder) ~>
+		on-stream-drive-folder-updated(folder) {
 			current = if @folder? then @folder.id else null
 			if current != folder.parent_id
 				@remove-folder folder
 			else
 				@add-folder folder, true
 
-		@_move = (ev) ~>
+		@_move = (ev) =>
 			@move ev.item.folder
 
-		@move = (target-folder) ~>
+		move(target-folder) {
 			@cd target-folder
 
-		@cd = (target-folder, silent = false) ~>
-			@file = null
+		cd(target-folder, silent = false) {
+			this.file = null
 
-			if target-folder? and typeof target-folder == \object
+			if target-folder? and typeof target-folder == 'object' 
 				target-folder = target-folder.id
 
 			if target-folder == null
 				@go-root!
 				return
 
-			@loading = true
-			@update!
+			this.loading = true
+			this.update();
 
-			@api \drive/folders/show do
+			this.api 'drive/folders/show' do
 				folder_id: target-folder
-			.then (folder) ~>
-				@folder = folder
-				@hierarchy-folders = []
+			.then (folder) =>
+				this.folder = folder
+				this.hierarchy-folders = []
 
-				x = (f) ~>
+				x = (f) =>
 					@hierarchy-folders.unshift f
 					if f.parent?
 						x f.parent
@@ -220,18 +220,18 @@
 				if folder.parent?
 					x folder.parent
 
-				@update!
-				@trigger \open-folder @folder, silent
+				this.update();
+				this.trigger 'open-folder' @folder, silent
 				@load!
 			.catch (err, text-status) ->
 				console.error err
 
-		@add-folder = (folder, unshift = false) ~>
+		add-folder(folder, unshift = false) {
 			current = if @folder? then @folder.id else null
 			if current != folder.parent_id
 				return
 
-			if (@folders.some (f) ~> f.id == folder.id)
+			if (@folders.some (f) => f.id == folder.id)
 				return
 
 			if unshift
@@ -239,17 +239,17 @@
 			else
 				@folders.push folder
 
-			@update!
+			this.update();
 
-		@add-file = (file, unshift = false) ~>
+		add-file(file, unshift = false) {
 			current = if @folder? then @folder.id else null
 			if current != file.folder_id
 				return
 
-			if (@files.some (f) ~> f.id == file.id)
+			if (@files.some (f) => f.id == file.id)
 				exist = (@files.map (f) -> f.id).index-of file.id
 				@files[exist] = file
-				@update!
+				this.update();
 				return
 
 			if unshift
@@ -257,38 +257,38 @@
 			else
 				@files.push file
 
-			@update!
+			this.update();
 
-		@remove-folder = (folder) ~>
-			if typeof folder == \object
+		remove-folder(folder) {
+			if typeof folder == 'object' 
 				folder = folder.id
-			@folders = @folders.filter (f) -> f.id != folder
-			@update!
+			this.folders = @folders.filter (f) -> f.id != folder
+			this.update();
 
-		@remove-file = (file) ~>
-			if typeof file == \object
+		remove-file(file) {
+			if typeof file == 'object' 
 				file = file.id
-			@files = @files.filter (f) -> f.id != file
-			@update!
+			this.files = @files.filter (f) -> f.id != file
+			this.update();
 
-		@go-root = ~>
+		go-root() {
 			if @folder != null or @file != null
-				@file = null
-				@folder = null
-				@hierarchy-folders = []
-				@update!
-				@trigger \move-root
+				this.file = null
+				this.folder = null
+				this.hierarchy-folders = []
+				this.update();
+				this.trigger('move-root');
 				@load!
 
-		@load = ~>
-			@folders = []
-			@files = []
-			@more-folders = false
-			@more-files = false
-			@loading = true
-			@update!
+		load() {
+			this.folders = []
+			this.files = []
+			this.more-folders = false
+			this.more-files = false
+			this.loading = true
+			this.update();
 
-			@trigger \begin-load
+			this.trigger('begin-load');
 
 			load-folders = null
 			load-files = null
@@ -296,74 +296,74 @@
 			folders-max = 20
 			files-max = 20
 
-			# フォルダ一覧取得
-			@api \drive/folders do
+			// フォルダ一覧取得
+			this.api 'drive/folders' do
 				folder_id: if @folder? then @folder.id else null
 				limit: folders-max + 1
-			.then (folders) ~>
+			.then (folders) =>
 				if folders.length == folders-max + 1
-					@more-folders = true
+					this.more-folders = true
 					folders.pop!
 				load-folders := folders
 				complete!
-			.catch (err, text-status) ~>
+			.catch (err, text-status) =>
 				console.error err
 
-			# ファイル一覧取得
-			@api \drive/files do
+			// ファイル一覧取得
+			this.api 'drive/files' do
 				folder_id: if @folder? then @folder.id else null
 				limit: files-max + 1
-			.then (files) ~>
+			.then (files) =>
 				if files.length == files-max + 1
-					@more-files = true
+					this.more-files = true
 					files.pop!
 				load-files := files
 				complete!
-			.catch (err, text-status) ~>
+			.catch (err, text-status) =>
 				console.error err
 
 			flag = false
-			complete = ~>
+			complete = =>
 				if flag
-					load-folders.for-each (folder) ~>
+					load-folders.for-each (folder) =>
 						@add-folder folder
-					load-files.for-each (file) ~>
+					load-files.for-each (file) =>
 						@add-file file
-					@loading = false
-					@update!
+					this.loading = false
+					this.update();
 
-					@trigger \loaded
+					this.trigger('loaded');
 				else
 					flag := true
-					@trigger \load-mid
+					this.trigger('load-mid');
 
-		@choose-file = (file) ~>
+		choose-file(file) {
 			if @is-select-mode
-				exist = @selected-files.some (f) ~> f.id == file.id
+				exist = @selected-files.some (f) => f.id == file.id
 				if exist
-					@selected-files = (@selected-files.filter (f) ~> f.id != file.id)
+					selected-files(@selected-files.filter (f) { f.id != file.id)
 				else
 					@selected-files.push file
-				@update!
-				@trigger \change-selected @selected-files
+				this.update();
+				this.trigger 'change-selected' @selected-files
 			else
 				@cf file
 
-		@cf = (file, silent = false) ~>
-			if typeof file == \object
+		cf(file, silent = false) {
+			if typeof file == 'object' 
 				file = file.id
 
-			@loading = true
-			@update!
+			this.loading = true
+			this.update();
 
-			@api \drive/files/show do
+			this.api 'drive/files/show' do
 				file_id: file
-			.then (file) ~>
-				@file = file
-				@folder = null
-				@hierarchy-folders = []
+			.then (file) =>
+				this.file = file
+				this.folder = null
+				this.hierarchy-folders = []
 
-				x = (f) ~>
+				x = (f) =>
 					@hierarchy-folders.unshift f
 					if f.parent?
 						x f.parent
@@ -371,7 +371,7 @@
 				if file.folder?
 					x file.folder
 
-				@update!
-				@trigger \open-file @file, silent
+				this.update();
+				this.trigger 'open-file' @file, silent
 	</script>
 </mk-drive>
diff --git a/src/web/app/mobile/tags/drive/file-viewer.tag b/src/web/app/mobile/tags/drive/file-viewer.tag
index a0d4c4445..86f6ca0c5 100644
--- a/src/web/app/mobile/tags/drive/file-viewer.tag
+++ b/src/web/app/mobile/tags/drive/file-viewer.tag
@@ -180,22 +180,22 @@
 
 	</style>
 	<script>
-		@bytes-to-size = require '../../../common/scripts/bytes-to-size.js'
-		@get-gcd = require '../../../common/scripts/gcd.js'
+		this.bytes-to-size = require('../../../common/scripts/bytes-to-size.js');
+		this.get-gcd = require('../../../common/scripts/gcd.js');
 
-		@mixin \api
+		this.mixin('api');
 
-		@file = @opts.file
-		@kind = @file.type.split \/ .0
+		this.file = this.opts.file
+		this.kind = @file.type.split '/' .0
 
-		@rename = ~>
+		rename() {
 			name = window.prompt '名前を変更' @file.name
 			if name? and name != '' and name != @file.name
-				@api \drive/files/update do
+				this.api 'drive/files/update' do
 					file_id: @file.id
 					name: name
-				.then ~>
-					@parent.cf @file, true
+				.then =>
+					this.parent.cf @file, true
 
 	</script>
 </mk-drive-file-viewer>
diff --git a/src/web/app/mobile/tags/drive/file.tag b/src/web/app/mobile/tags/drive/file.tag
index 95f91e5eb..16fa74b4b 100644
--- a/src/web/app/mobile/tags/drive/file.tag
+++ b/src/web/app/mobile/tags/drive/file.tag
@@ -122,16 +122,16 @@
 
 	</style>
 	<script>
-		@bytes-to-size = require '../../../common/scripts/bytes-to-size.js'
+		this.bytes-to-size = require('../../../common/scripts/bytes-to-size.js');
 
-		@browser = @parent
-		@file = @opts.file
-		@is-selected = @browser.selected-files.some (f) ~> f.id == @file.id
+		this.browser = this.parent
+		this.file = this.opts.file
+		this.is-selected = @browser.selected-files.some (f) => f.id == @file.id
 
-		@browser.on \change-selected (selects) ~>
-			@is-selected = selects.some (f) ~> f.id == @file.id
+		@browser.on('change-selected', (selects) => {
+			this.is-selected = selects.some (f) => f.id == @file.id
 
-		@onclick = ~>
+		onclick() {
 			@browser.choose-file @file
 	</script>
 </mk-drive-file>
diff --git a/src/web/app/mobile/tags/drive/folder.tag b/src/web/app/mobile/tags/drive/folder.tag
index 82bef0262..aeb1601a6 100644
--- a/src/web/app/mobile/tags/drive/folder.tag
+++ b/src/web/app/mobile/tags/drive/folder.tag
@@ -37,10 +37,10 @@
 
 	</style>
 	<script>
-		@browser = @parent
-		@folder = @opts.folder
+		this.browser = this.parent
+		this.folder = this.opts.folder
 
-		@onclick = ~>
+		onclick() {
 			@browser.move @folder
 	</script>
 </mk-drive-folder>
diff --git a/src/web/app/mobile/tags/follow-button.tag b/src/web/app/mobile/tags/follow-button.tag
index ac7058aeb..99936530c 100644
--- a/src/web/app/mobile/tags/follow-button.tag
+++ b/src/web/app/mobile/tags/follow-button.tag
@@ -48,58 +48,58 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \is-promise
-		@mixin \stream
+		this.mixin('api');
+		this.mixin('is-promise');
+		this.mixin('stream');
 
-		@user = null
-		@user-promise = if @is-promise @opts.user then @opts.user else Promise.resolve @opts.user
-		@init = true
-		@wait = false
+		this.user = null
+		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
+		this.init = true
+		this.wait = false
 
-		@on \mount ~>
-			@user-promise.then (user) ~>
-				@user = user
-				@init = false
-				@update!
-				@stream.on \follow @on-stream-follow
-				@stream.on \unfollow @on-stream-unfollow
+		this.on('mount', () => {
+			@user-promise.then (user) =>
+				this.user = user
+				this.init = false
+				this.update();
+				@stream.on 'follow' this.on-stream-follow
+				@stream.on 'unfollow' this.on-stream-unfollow
 
-		@on \unmount ~>
-			@stream.off \follow @on-stream-follow
-			@stream.off \unfollow @on-stream-unfollow
+		this.on('unmount', () => {
+			@stream.off 'follow' this.on-stream-follow
+			@stream.off 'unfollow' this.on-stream-unfollow
 
-		@on-stream-follow = (user) ~>
+		on-stream-follow(user) {
 			if user.id == @user.id
-				@user = user
-				@update!
+				this.user = user
+				this.update();
 
-		@on-stream-unfollow = (user) ~>
+		on-stream-unfollow(user) {
 			if user.id == @user.id
-				@user = user
-				@update!
+				this.user = user
+				this.update();
 
-		@onclick = ~>
-			@wait = true
+		onclick() {
+			this.wait = true
 			if @user.is_following
-				@api \following/delete do
+				this.api 'following/delete' do
 					user_id: @user.id
-				.then ~>
+				.then =>
 					@user.is_following = false
 				.catch (err) ->
 					console.error err
-				.then ~>
-					@wait = false
-					@update!
+				.then =>
+					this.wait = false
+					this.update();
 			else
-				@api \following/create do
+				this.api 'following/create' do
 					user_id: @user.id
-				.then ~>
+				.then =>
 					@user.is_following = true
 				.catch (err) ->
 					console.error err
-				.then ~>
-					@wait = false
-					@update!
+				.then =>
+					this.wait = false
+					this.update();
 	</script>
 </mk-follow-button>
diff --git a/src/web/app/mobile/tags/home-timeline.tag b/src/web/app/mobile/tags/home-timeline.tag
index 2aa912714..98c3a0821 100644
--- a/src/web/app/mobile/tags/home-timeline.tag
+++ b/src/web/app/mobile/tags/home-timeline.tag
@@ -6,38 +6,38 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \stream
+		this.mixin('api');
+		this.mixin('stream');
 
-		@init = new Promise (res, rej) ~>
-			@api \posts/timeline
-			.then (posts) ~>
+		this.init = new Promise (res, rej) =>
+			this.api 'posts/timeline' 
+			.then (posts) =>
 				res posts
-				@trigger \loaded
+				this.trigger('loaded');
 
-		@on \mount ~>
-			@stream.on \post @on-stream-post
-			@stream.on \follow @on-stream-follow
-			@stream.on \unfollow @on-stream-unfollow
+		this.on('mount', () => {
+			@stream.on 'post' this.on-stream-post
+			@stream.on 'follow' this.on-stream-follow
+			@stream.on 'unfollow' this.on-stream-unfollow
 
-		@on \unmount ~>
-			@stream.off \post @on-stream-post
-			@stream.off \follow @on-stream-follow
-			@stream.off \unfollow @on-stream-unfollow
+		this.on('unmount', () => {
+			@stream.off 'post' this.on-stream-post
+			@stream.off 'follow' this.on-stream-follow
+			@stream.off 'unfollow' this.on-stream-unfollow
 
-		@more = ~>
-			@api \posts/timeline do
-				max_id: @refs.timeline.tail!.id
+		more() {
+			this.api 'posts/timeline' do
+				max_id: this.refs.timeline.tail!.id
 
-		@on-stream-post = (post) ~>
-			@is-empty = false
-			@update!
-			@refs.timeline.add-post post
+		on-stream-post(post) {
+			this.is-empty = false
+			this.update();
+			this.refs.timeline.add-post post
 
-		@on-stream-follow = ~>
+		on-stream-follow() {
 			@fetch!
 
-		@on-stream-unfollow = ~>
+		on-stream-unfollow() {
 			@fetch!
 	</script>
 </mk-home-timeline>
diff --git a/src/web/app/mobile/tags/home.tag b/src/web/app/mobile/tags/home.tag
index 78141ca9a..0ca62cdb0 100644
--- a/src/web/app/mobile/tags/home.tag
+++ b/src/web/app/mobile/tags/home.tag
@@ -13,8 +13,8 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			@refs.tl.on \loaded ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			this.refs.tl.on('loaded', () => {
+				this.trigger('loaded');
 	</script>
 </mk-home>
diff --git a/src/web/app/mobile/tags/images-viewer.tag b/src/web/app/mobile/tags/images-viewer.tag
index 05dc744cd..6ff03ba63 100644
--- a/src/web/app/mobile/tags/images-viewer.tag
+++ b/src/web/app/mobile/tags/images-viewer.tag
@@ -18,10 +18,10 @@
 
 	</style>
 	<script>
-		@images = @opts.images
-		@image = @images.0
+		this.images = this.opts.images
+		this.image = @images.0
 
-		@click = ~>
+		click() {
 			window.open @image.url
 	</script>
 </mk-images-viewer>
diff --git a/src/web/app/mobile/tags/notification-preview.tag b/src/web/app/mobile/tags/notification-preview.tag
index c146c6f0f..800d1b434 100644
--- a/src/web/app/mobile/tags/notification-preview.tag
+++ b/src/web/app/mobile/tags/notification-preview.tag
@@ -107,7 +107,7 @@
 
 	</style>
 	<script>
-		@mixin \get-post-summary
-		@notification = @opts.notification
+		this.mixin('get-post-summary');
+		this.notification = this.opts.notification
 	</script>
 </mk-notification-preview>
diff --git a/src/web/app/mobile/tags/notification.tag b/src/web/app/mobile/tags/notification.tag
index b619c6698..9cf61fe40 100644
--- a/src/web/app/mobile/tags/notification.tag
+++ b/src/web/app/mobile/tags/notification.tag
@@ -167,7 +167,7 @@
 
 	</style>
 	<script>
-		@mixin \get-post-summary
-		@notification = @opts.notification
+		this.mixin('get-post-summary');
+		this.notification = this.opts.notification
 	</script>
 </mk-notification>
diff --git a/src/web/app/mobile/tags/notifications.tag b/src/web/app/mobile/tags/notifications.tag
index 820749579..59bcebaa4 100644
--- a/src/web/app/mobile/tags/notifications.tag
+++ b/src/web/app/mobile/tags/notifications.tag
@@ -57,34 +57,34 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \stream
-		@mixin \get-post-summary
+		this.mixin('api');
+		this.mixin('stream');
+		this.mixin('get-post-summary');
 
-		@notifications = []
-		@loading = true
+		this.notifications = []
+		this.loading = true
 
-		@on \mount ~>
-			@api \i/notifications
-			.then (notifications) ~>
-				@notifications = notifications
-				@loading = false
-				@update!
-				@trigger \loaded
+		this.on('mount', () => {
+			this.api 'i/notifications' 
+			.then (notifications) =>
+				this.notifications = notifications
+				this.loading = false
+				this.update();
+				this.trigger('loaded');
 			.catch (err, text-status) ->
 				console.error err
 
-			@stream.on \notification @on-notification
+			@stream.on 'notification' this.on-notification
 
-		@on \unmount ~>
-			@stream.off \notification @on-notification
+		this.on('unmount', () => {
+			@stream.off 'notification' this.on-notification
 
-		@on-notification = (notification) ~>
+		on-notification(notification) {
 			@notifications.unshift notification
-			@update!
+			this.update();
 
-		@on \update ~>
-			@notifications.for-each (notification) ~>
+		this.on('update', () => {
+			@notifications.for-each (notification) =>
 				date = (new Date notification.created_at).get-date!
 				month = (new Date notification.created_at).get-month! + 1
 				notification._date = date
diff --git a/src/web/app/mobile/tags/notify.tag b/src/web/app/mobile/tags/notify.tag
index aa45ce0cf..5d27860e4 100644
--- a/src/web/app/mobile/tags/notify.tag
+++ b/src/web/app/mobile/tags/notify.tag
@@ -16,22 +16,22 @@
 
 	</style>
 	<script>
-		@on \mount ~>
-			Velocity @root, {
-				bottom: \0px
+		this.on('mount', () => {
+			Velocity this.root, {
+				bottom: '0px' 
 			} {
 				duration: 500ms
-				easing: \ease-out
+				easing: 'ease-out' 
 			}
 
-			set-timeout ~>
-				Velocity @root, {
-					bottom: \-64px
+			setTimeout =>
+				Velocity this.root, {
+					bottom: '-64px' 
 				} {
 					duration: 500ms
-					easing: \ease-out
-					complete: ~>
-						@unmount!
+					easing: 'ease-out' 
+					complete: =>
+						this.unmount();
 				}
 			, 6000ms
 	</script>
diff --git a/src/web/app/mobile/tags/page/drive.tag b/src/web/app/mobile/tags/page/drive.tag
index ef83e4d5b..c3e16a704 100644
--- a/src/web/app/mobile/tags/page/drive.tag
+++ b/src/web/app/mobile/tags/page/drive.tag
@@ -8,53 +8,53 @@
 
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \ui-progress
+		this.mixin('ui');
+		this.mixin('ui-progress');
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey Drive'
-			@ui.trigger \title '<i class="fa fa-cloud"></i>ドライブ'
+			this.ui.trigger('title', '<i class="fa fa-cloud"></i>ドライブ');
 
-			@refs.ui.refs.browser.on \begin-load ~>
-				@Progress.start!
+			this.refs.ui.refs.browser.on('begin-load', () => {
+				this.Progress.start();
 
-			@refs.ui.refs.browser.on \loaded-mid ~>
-				@Progress.set 0.5
+			this.refs.ui.refs.browser.on('loaded-mid', () => {
+				this.Progress.set(0.5);
 
-			@refs.ui.refs.browser.on \loaded ~>
-				@Progress.done!
+			this.refs.ui.refs.browser.on('loaded', () => {
+				this.Progress.done();
 
-			@refs.ui.refs.browser.on \move-root ~>
+			this.refs.ui.refs.browser.on('move-root', () => {
 				title = 'Misskey Drive'
 
-				# Rewrite URL
-				history.push-state null, title, '/i/drive'
+				// Rewrite URL
+				history.pushState null, title, '/i/drive'
 
 				document.title = title
-				@ui.trigger \title '<i class="fa fa-cloud"></i>ドライブ'
+				this.ui.trigger('title', '<i class="fa fa-cloud"></i>ドライブ');
 
-			@refs.ui.refs.browser.on \open-folder (folder, silent) ~>
+			this.refs.ui.refs.browser.on('open-folder', (folder, silent) => {
 				title = folder.name + ' | Misskey Drive'
 
 				if !silent
-					# Rewrite URL
-					history.push-state null, title, '/i/drive/folder/' + folder.id
+					// Rewrite URL
+					history.pushState null, title, '/i/drive/folder/' + folder.id
 
 				document.title = title
-				# TODO: escape html characters in folder.name
-				@ui.trigger \title '<i class="fa fa-folder-open"></i>' + folder.name
+				// TODO: escape html characters in folder.name
+				this.ui.trigger('title', '<i class="fa fa-folder-open"></i>' + folder.name);
 
-			@refs.ui.refs.browser.on \open-file (file, silent) ~>
+			this.refs.ui.refs.browser.on('open-file', (file, silent) => {
 				title = file.name + ' | Misskey Drive'
 
 				if !silent
-					# Rewrite URL
-					history.push-state null, title, '/i/drive/file/' + file.id
+					// Rewrite URL
+					history.pushState null, title, '/i/drive/file/' + file.id
 
 				document.title = title
-				# TODO: escape html characters in file.name
-				@ui.trigger \title '<mk-file-type-icon class="icon"></mk-file-type-icon>' + file.name
-				riot.mount \mk-file-type-icon do
+				// TODO: escape html characters in file.name
+				this.ui.trigger('title', '<mk-file-type-icon class="icon"></mk-file-type-icon>' + file.name);
+				riot.mount 'mk-file-type-icon' do
 					type: file.type
 
 	</script>
diff --git a/src/web/app/mobile/tags/page/entrance.tag b/src/web/app/mobile/tags/page/entrance.tag
index 424c58da5..3ec43f0f6 100644
--- a/src/web/app/mobile/tags/page/entrance.tag
+++ b/src/web/app/mobile/tags/page/entrance.tag
@@ -43,18 +43,18 @@
 
 	</style>
 	<script>
-		@mode = \signin
+		this.mode = 'signin' 
 
-		@signup = ~>
-			@mode = \signup
-			@update!
+		signup() {
+			this.mode = 'signup' 
+			this.update();
 
-		@signin = ~>
-			@mode = \signin
-			@update!
+		signin() {
+			this.mode = 'signin' 
+			this.update();
 
-		@introduction = ~>
-			@mode = \introduction
-			@update!
+		introduction() {
+			this.mode = 'introduction' 
+			this.update();
 	</script>
 </mk-entrance>
diff --git a/src/web/app/mobile/tags/page/home.tag b/src/web/app/mobile/tags/page/home.tag
index 947e119b0..db87483a9 100644
--- a/src/web/app/mobile/tags/page/home.tag
+++ b/src/web/app/mobile/tags/page/home.tag
@@ -8,38 +8,38 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \ui
-		@mixin \ui-progress
-		@mixin \stream
-		@mixin \get-post-summary
+		this.mixin('i');
+		this.mixin('ui');
+		this.mixin('ui-progress');
+		this.mixin('stream');
+		this.mixin('get-post-summary');
 
-		@unread-count = 0
+		this.unread-count = 0
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey'
-			@ui.trigger \title '<i class="fa fa-home"></i>ホーム'
+			this.ui.trigger('title', '<i class="fa fa-home"></i>ホーム');
 
-			@Progress.start!
+			this.Progress.start();
 
-			@stream.on \post @on-stream-post
-			document.add-event-listener \visibilitychange @window-on-visibilitychange, false
+			@stream.on 'post' this.on-stream-post
+			document.add-event-listener 'visibilitychange' @window-on-visibilitychange, false
 
-			@refs.ui.refs.home.on \loaded ~>
-				@Progress.done!
+			this.refs.ui.refs.home.on('loaded', () => {
+				this.Progress.done();
 
-		@on \unmount ~>
-			@stream.off \post @on-stream-post
-			document.remove-event-listener \visibilitychange @window-on-visibilitychange
+		this.on('unmount', () => {
+			@stream.off 'post' this.on-stream-post
+			document.remove-event-listener 'visibilitychange' @window-on-visibilitychange
 
-		@on-stream-post = (post) ~>
+		on-stream-post(post) {
 			if document.hidden and post.user_id !== @I.id
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
-		@window-on-visibilitychange = ~>
+		window-on-visibilitychange() {
 			if !document.hidden
-				@unread-count = 0
+				this.unread-count = 0
 				document.title = 'Misskey'
 	</script>
 </mk-home-page>
diff --git a/src/web/app/mobile/tags/page/messaging-room.tag b/src/web/app/mobile/tags/page/messaging-room.tag
index 2216d0c46..6b699143c 100644
--- a/src/web/app/mobile/tags/page/messaging-room.tag
+++ b/src/web/app/mobile/tags/page/messaging-room.tag
@@ -7,21 +7,21 @@
 			display block
 	</style>
 	<script>
-		@mixin \api
-		@mixin \ui
+		this.mixin('api');
+		this.mixin('ui');
 
-		@fetching = true
+		this.fetching = true
 
-		@on \mount ~>
-			@api \users/show do
-				username: @opts.username
-			.then (user) ~>
-				@fetching = false
-				@user = user
-				@update!
+		this.on('mount', () => {
+			this.api 'users/show' do
+				username: this.opts.username
+			.then (user) =>
+				this.fetching = false
+				this.user = user
+				this.update();
 
 				document.title = 'メッセージ: ' + user.name + ' | Misskey'
-				# TODO: ユーザー名をエスケープ
-				@ui.trigger \title '<i class="fa fa-comments-o"></i>' + user.name
+				// TODO: ユーザー名をエスケープ
+				this.ui.trigger('title', '<i class="fa fa-comments-o"></i>'); + user.name
 	</script>
 </mk-messaging-room-page>
diff --git a/src/web/app/mobile/tags/page/messaging.tag b/src/web/app/mobile/tags/page/messaging.tag
index dd277f46e..1af983b1d 100644
--- a/src/web/app/mobile/tags/page/messaging.tag
+++ b/src/web/app/mobile/tags/page/messaging.tag
@@ -7,14 +7,14 @@
 			display block
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \page
+		this.mixin('ui');
+		this.mixin('page');
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey | メッセージ'
-			@ui.trigger \title '<i class="fa fa-comments-o"></i>メッセージ'
+			this.ui.trigger('title', '<i class="fa fa-comments-o"></i>メッセージ');
 
-			@refs.ui.refs.index.on \navigate-user (user) ~>
+			this.refs.ui.refs.index.on('navigate-user', (user) => {
 				@page '/i/messaging/' + user.username
 
 	</script>
diff --git a/src/web/app/mobile/tags/page/notifications.tag b/src/web/app/mobile/tags/page/notifications.tag
index 18b6cc283..b33386fb8 100644
--- a/src/web/app/mobile/tags/page/notifications.tag
+++ b/src/web/app/mobile/tags/page/notifications.tag
@@ -8,16 +8,16 @@
 
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \ui-progress
+		this.mixin('ui');
+		this.mixin('ui-progress');
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey | 通知'
-			@ui.trigger \title '<i class="fa fa-bell-o"></i>通知'
+			this.ui.trigger('title', '<i class="fa fa-bell-o"></i>通知');
 
-			@Progress.start!
+			this.Progress.start();
 
-			@refs.ui.refs.notifications.on \loaded ~>
-				@Progress.done!
+			this.refs.ui.refs.notifications.on('loaded', () => {
+				this.Progress.done();
 	</script>
 </mk-notifications-page>
diff --git a/src/web/app/mobile/tags/page/post.tag b/src/web/app/mobile/tags/page/post.tag
index a8ffb1c3c..69a24c552 100644
--- a/src/web/app/mobile/tags/page/post.tag
+++ b/src/web/app/mobile/tags/page/post.tag
@@ -18,21 +18,21 @@
 
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \ui-progress
+		this.mixin('ui');
+		this.mixin('ui-progress');
 
-		@post = @opts.post
+		this.post = this.opts.post
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey'
-			@ui.trigger \title '<i class="fa fa-sticky-note-o"></i>投稿'
+			this.ui.trigger('title', '<i class="fa fa-sticky-note-o"></i>投稿');
 
-			@Progress.start!
+			this.Progress.start();
 
-			@refs.ui.refs.post.on \post-fetched ~>
-				@Progress.set 0.5
+			this.refs.ui.refs.post.on('post-fetched', () => {
+				this.Progress.set(0.5);
 
-			@refs.ui.refs.post.on \loaded ~>
-				@Progress.done!
+			this.refs.ui.refs.post.on('loaded', () => {
+				this.Progress.done();
 	</script>
 </mk-post-page>
diff --git a/src/web/app/mobile/tags/page/search.tag b/src/web/app/mobile/tags/page/search.tag
index 31de7d962..4dde50ab8 100644
--- a/src/web/app/mobile/tags/page/search.tag
+++ b/src/web/app/mobile/tags/page/search.tag
@@ -8,17 +8,17 @@
 
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \ui-progress
+		this.mixin('ui');
+		this.mixin('ui-progress');
 
-		@on \mount ~>
-			document.title = '検索: ' + @opts.query + ' | Misskey'
-			# TODO: クエリをHTMLエスケープ
-			@ui.trigger \title '<i class="fa fa-search"></i>' + @opts.query
+		this.on('mount', () => {
+			document.title = '検索: ' + this.opts.query + ' | Misskey'
+			// TODO: クエリをHTMLエスケープ
+			this.ui.trigger('title', '<i class="fa fa-search"></i>'); + this.opts.query
 
-			@Progress.start!
+			this.Progress.start();
 
-			@refs.ui.refs.search.on \loaded ~>
-				@Progress.done!
+			this.refs.ui.refs.search.on('loaded', () => {
+				this.Progress.done();
 	</script>
 </mk-search-page>
diff --git a/src/web/app/mobile/tags/page/settings.tag b/src/web/app/mobile/tags/page/settings.tag
index 99e7569f5..5e06a302e 100644
--- a/src/web/app/mobile/tags/page/settings.tag
+++ b/src/web/app/mobile/tags/page/settings.tag
@@ -13,10 +13,10 @@
 			display block
 	</style>
 	<script>
-		@mixin \ui
+		this.mixin('ui');
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey | 設定'
-			@ui.trigger \title '<i class="fa fa-cog"></i>設定'
+			this.ui.trigger('title', '<i class="fa fa-cog"></i>設定');
 	</script>
 </mk-settings-page>
diff --git a/src/web/app/mobile/tags/page/settings/api.tag b/src/web/app/mobile/tags/page/settings/api.tag
index 69f4a47db..039792c0a 100644
--- a/src/web/app/mobile/tags/page/settings/api.tag
+++ b/src/web/app/mobile/tags/page/settings/api.tag
@@ -7,10 +7,10 @@
 			display block
 	</style>
 	<script>
-		@mixin \ui
+		this.mixin('ui');
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey | API'
-			@ui.trigger \title '<i class="fa fa-key"></i>API'
+			this.ui.trigger('title', '<i class="fa fa-key"></i>API');
 	</script>
 </mk-api-info-page>
diff --git a/src/web/app/mobile/tags/page/settings/authorized-apps.tag b/src/web/app/mobile/tags/page/settings/authorized-apps.tag
index abb8ba0fc..1415f11d0 100644
--- a/src/web/app/mobile/tags/page/settings/authorized-apps.tag
+++ b/src/web/app/mobile/tags/page/settings/authorized-apps.tag
@@ -7,10 +7,10 @@
 			display block
 	</style>
 	<script>
-		@mixin \ui
+		this.mixin('ui');
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey | アプリケーション'
-			@ui.trigger \title '<i class="fa fa-puzzle-piece"></i>アプリケーション'
+			this.ui.trigger('title', '<i class="fa fa-puzzle-piece"></i>アプリケーション');
 	</script>
 </mk-authorized-apps-page>
diff --git a/src/web/app/mobile/tags/page/settings/signin.tag b/src/web/app/mobile/tags/page/settings/signin.tag
index 5886b53f9..092cd6441 100644
--- a/src/web/app/mobile/tags/page/settings/signin.tag
+++ b/src/web/app/mobile/tags/page/settings/signin.tag
@@ -7,10 +7,10 @@
 			display block
 	</style>
 	<script>
-		@mixin \ui
+		this.mixin('ui');
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey | ログイン履歴'
-			@ui.trigger \title '<i class="fa fa-sign-in"></i>ログイン履歴'
+			this.ui.trigger('title', '<i class="fa fa-sign-in"></i>ログイン履歴');
 	</script>
 </mk-signin-history-page>
diff --git a/src/web/app/mobile/tags/page/settings/twitter.tag b/src/web/app/mobile/tags/page/settings/twitter.tag
index f6cde2e5a..87550efe2 100644
--- a/src/web/app/mobile/tags/page/settings/twitter.tag
+++ b/src/web/app/mobile/tags/page/settings/twitter.tag
@@ -7,10 +7,10 @@
 			display block
 	</style>
 	<script>
-		@mixin \ui
+		this.mixin('ui');
 
-		@on \mount ~>
+		this.on('mount', () => {
 			document.title = 'Misskey | Twitter連携'
-			@ui.trigger \title '<i class="fa fa-twitter"></i>Twitter連携'
+			this.ui.trigger('title', '<i class="fa fa-twitter"></i>Twitter連携');
 	</script>
 </mk-twitter-setting-page>
diff --git a/src/web/app/mobile/tags/page/user-followers.tag b/src/web/app/mobile/tags/page/user-followers.tag
index 5856e60e0..12338e796 100644
--- a/src/web/app/mobile/tags/page/user-followers.tag
+++ b/src/web/app/mobile/tags/page/user-followers.tag
@@ -8,29 +8,29 @@
 
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \ui-progress
-		@mixin \api
+		this.mixin('ui');
+		this.mixin('ui-progress');
+		this.mixin('api');
 
-		@fetching = true
-		@user = null
+		this.fetching = true
+		this.user = null
 
-		@on \mount ~>
-			@Progress.start!
+		this.on('mount', () => {
+			this.Progress.start();
 
-			@api \users/show do
-				username: @opts.user
-			.then (user) ~>
-				@user = user
-				@fetching = false
+			this.api 'users/show' do
+				username: this.opts.user
+			.then (user) =>
+				this.user = user
+				this.fetching = false
 
 				document.title = user.name + 'のフォロワー | Misskey'
-				# TODO: ユーザー名をエスケープ
-				@ui.trigger \title '<img src="' + user.avatar_url + '?thumbnail&size=64">' + user.name + 'のフォロワー'
+				// TODO: ユーザー名をエスケープ
+				this.ui.trigger('title', '<img src="'); + user.avatar_url + '?thumbnail&size=64">' + user.name + 'のフォロワー'
 
-				@update!
+				this.update();
 
-				@refs.ui.refs.list.on \loaded ~>
-					@Progress.done!
+				this.refs.ui.refs.list.on('loaded', () => {
+					this.Progress.done();
 	</script>
 </mk-user-followers-page>
diff --git a/src/web/app/mobile/tags/page/user-following.tag b/src/web/app/mobile/tags/page/user-following.tag
index 14b006d3f..088c45832 100644
--- a/src/web/app/mobile/tags/page/user-following.tag
+++ b/src/web/app/mobile/tags/page/user-following.tag
@@ -8,29 +8,29 @@
 
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \ui-progress
-		@mixin \api
+		this.mixin('ui');
+		this.mixin('ui-progress');
+		this.mixin('api');
 
-		@fetching = true
-		@user = null
+		this.fetching = true
+		this.user = null
 
-		@on \mount ~>
-			@Progress.start!
+		this.on('mount', () => {
+			this.Progress.start();
 
-			@api \users/show do
-				username: @opts.user
-			.then (user) ~>
-				@user = user
-				@fetching = false
+			this.api 'users/show' do
+				username: this.opts.user
+			.then (user) =>
+				this.user = user
+				this.fetching = false
 
 				document.title = user.name + 'のフォロー | Misskey'
-				# TODO: ユーザー名をエスケープ
-				@ui.trigger \title '<img src="' + user.avatar_url + '?thumbnail&size=64">' + user.name + 'のフォロー'
+				// TODO: ユーザー名をエスケープ
+				this.ui.trigger('title', '<img src="'); + user.avatar_url + '?thumbnail&size=64">' + user.name + 'のフォロー'
 
-				@update!
+				this.update();
 
-				@refs.ui.refs.list.on \loaded ~>
-					@Progress.done!
+				this.refs.ui.refs.list.on('loaded', () => {
+					this.Progress.done();
 	</script>
 </mk-user-following-page>
diff --git a/src/web/app/mobile/tags/page/user.tag b/src/web/app/mobile/tags/page/user.tag
index 0ac8ed4e2..4215ca2c3 100644
--- a/src/web/app/mobile/tags/page/user.tag
+++ b/src/web/app/mobile/tags/page/user.tag
@@ -8,18 +8,18 @@
 
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \ui-progress
+		this.mixin('ui');
+		this.mixin('ui-progress');
 
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@on \mount ~>
-			@Progress.start!
+		this.on('mount', () => {
+			this.Progress.start();
 
-			@refs.ui.refs.user.on \loaded (user) ~>
-				@Progress.done!
+			this.refs.ui.refs.user.on('loaded', (user) => {
+				this.Progress.done();
 				document.title = user.name + ' | Misskey'
-				# TODO: ユーザー名をエスケープ
-				@ui.trigger \title '<i class="fa fa-user"></i>' + user.name
+				// TODO: ユーザー名をエスケープ
+				this.ui.trigger('title', '<i class="fa fa-user"></i>'); + user.name
 	</script>
 </mk-user-page>
diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag
index 3856df080..7d19a96d5 100644
--- a/src/web/app/mobile/tags/post-detail.tag
+++ b/src/web/app/mobile/tags/post-detail.tag
@@ -329,102 +329,102 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \text
-		@mixin \get-post-summary
-		@mixin \open-post-form
+		this.mixin('api');
+		this.mixin('text');
+		this.mixin('get-post-summary');
+		this.mixin('open-post-form');
 
-		@fetching = true
-		@loading-context = false
-		@content = null
-		@post = null
+		this.fetching = true
+		this.loading-context = false
+		this.content = null
+		this.post = null
 
-		@on \mount ~>
-			@api \posts/show do
-				post_id: @opts.post
-			.then (post) ~>
-				@post = post
-				@is-repost = @post.repost?
-				@p = if @is-repost then @post.repost else @post
-				@summary = @get-post-summary @p
-				@trigger \loaded
-				@fetching = false
-				@update!
+		this.on('mount', () => {
+			this.api 'posts/show' do
+				post_id: this.opts.post
+			.then (post) =>
+				this.post = post
+				this.is-repost = @post.repost?
+				this.p = if @is-repost then @post.repost else @post
+				this.summary = @get-post-summary @p
+				this.trigger('loaded');
+				this.fetching = false
+				this.update();
 
 				if @p.text?
 					tokens = @analyze @p.text
-					@refs.text.innerHTML = @compile tokens
+					this.refs.text.innerHTML = @compile tokens
 
-					@refs.text.children.for-each (e) ~>
-						if e.tag-name == \MK-URL
+					this.refs.text.children.for-each (e) =>
+						if e.tag-name == 'MK-URL' 
 							riot.mount e
 
-					# URLをプレビュー
+					// URLをプレビュー
 					tokens
-						.filter (t) -> t.type == \link
-						.map (t) ~>
-							@preview = @refs.text.append-child document.create-element \mk-url-preview
+						.filter (t) -> t.type == 'link' 
+						.map (t) =>
+							this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
 							riot.mount @preview, do
 								url: t.content
 
-				# Get likes
-				@api \posts/likes do
+				// Get likes
+				this.api 'posts/likes' do
 					post_id: @p.id
 					limit: 8
-				.then (likes) ~>
-					@likes = likes
-					@update!
+				.then (likes) =>
+					this.likes = likes
+					this.update();
 
-				# Get reposts
-				@api \posts/reposts do
+				// Get reposts
+				this.api 'posts/reposts' do
 					post_id: @p.id
 					limit: 8
-				.then (reposts) ~>
-					@reposts = reposts
-					@update!
+				.then (reposts) =>
+					this.reposts = reposts
+					this.update();
 
-				# Get replies
-				@api \posts/replies do
+				// Get replies
+				this.api 'posts/replies' do
 					post_id: @p.id
 					limit: 8
-				.then (replies) ~>
-					@replies = replies
-					@update!
+				.then (replies) =>
+					this.replies = replies
+					this.update();
 
-		@reply = ~>
+		reply() {
 			@open-post-form do
 				reply: @p
 
-		@repost = ~>
+		repost() {
 			text = window.prompt '「' + @summary + '」をRepost'
 			if text?
-				@api \posts/create do
+				this.api 'posts/create' do
 					repost_id: @p.id
 					text: if text == '' then undefined else text
 
-		@like = ~>
+		like() {
 			if @p.is_liked
-				@api \posts/likes/delete do
+				this.api 'posts/likes/delete' do
 					post_id: @p.id
-				.then ~>
+				.then =>
 					@p.is_liked = false
-					@update!
+					this.update();
 			else
-				@api \posts/likes/create do
+				this.api 'posts/likes/create' do
 					post_id: @p.id
-				.then ~>
+				.then =>
 					@p.is_liked = true
-					@update!
+					this.update();
 
-		@load-context = ~>
-			@loading-context = true
+		load-context() {
+			this.loading-context = true
 
-			# Get context
-			@api \posts/context do
+			// Get context
+			this.api 'posts/context' do
 				post_id: @p.reply_to_id
-			.then (context) ~>
-				@context = context.reverse!
-				@loading-context = false
-				@update!
+			.then (context) =>
+				this.context = context.reverse!
+				this.loading-context = false
+				this.update();
 	</script>
 </mk-post-detail>
diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag
index 3d98a9832..e53339dd4 100644
--- a/src/web/app/mobile/tags/post-form.tag
+++ b/src/web/app/mobile/tags/post-form.tag
@@ -182,103 +182,103 @@
 
 	</style>
 	<script>
-		get-cat = require '../../common/scripts/get-cat'
+		get-cat = require('../../common/scripts/get-cat');
 
-		@mixin \api
+		this.mixin('api');
 
-		@wait = false
-		@uploadings = []
-		@files = []
-		@poll = false
+		this.wait = false
+		this.uploadings = []
+		this.files = []
+		this.poll = false
 
-		@on \mount ~>
-			@refs.uploader.on \uploaded (file) ~>
+		this.on('mount', () => {
+			this.refs.uploader.on('uploaded', (file) => {
 				@add-file file
 
-			@refs.uploader.on \change-uploads (uploads) ~>
-				@trigger \change-uploading-files uploads
+			this.refs.uploader.on('change-uploads', (uploads) => {
+				this.trigger 'change-uploading-files' uploads
 
-			@refs.text.focus!
+			this.refs.text.focus();
 
-		@onkeypress = (e) ~>
-			if (e.char-code == 10 || e.char-code == 13) && e.ctrl-key
+		onkeypress(e) {
+			if (e.char-code == 10 || e.char-code == 13) && e.ctrlKey
 				@post!
 			else
 				return true
 
-		@onpaste = (e) ~>
-			data = e.clipboard-data
+		onpaste(e) {
+			data = e.clipboardData
 			items = data.items
 			for i from 0 to items.length - 1
 				item = items[i]
 				switch (item.kind)
-					| \file =>
-						@upload item.get-as-file!
+					| 'file' =>
+						@upload item.getAsFile();
 			return true
 
-		@select-file = ~>
-			@refs.file.click!
+		select-file() {
+			this.refs.file.click!
 
-		@select-file-from-drive = ~>
-			browser = document.body.append-child document.create-element \mk-drive-selector
+		select-file-from-drive() {
+			browser = document.body.appendChild document.createElement 'mk-drive-selector' 
 			browser = riot.mount browser, do
 				multiple: true
 			.0
-			browser.on \selected (files) ~>
+			browser.on('selected', (files) => {
 				files.for-each @add-file
 
-		@change-file = ~>
-			files = @refs.file.files
+		change-file() {
+			files = this.refs.file.files
 			for i from 0 to files.length - 1
 				file = files.item i
 				@upload file
 
-		@upload = (file) ~>
-			@refs.uploader.upload file
+		upload(file) {
+			this.refs.uploader.upload file
 
-		@add-file = (file) ~>
-			file._remove = ~>
-				@files = @files.filter (x) -> x.id != file.id
-				@trigger \change-files @files
-				@update!
+		add-file(file) {
+			file._remove = =>
+				this.files = @files.filter (x) -> x.id != file.id
+				this.trigger 'change-files' @files
+				this.update();
 
 			@files.push file
-			@trigger \change-files @files
-			@update!
+			this.trigger 'change-files' @files
+			this.update();
 
-		@add-poll = ~>
-			@poll = true
+		add-poll() {
+			this.poll = true
 
-		@on-poll-destroyed = ~>
+		on-poll-destroyed() {
 			@update do
 				poll: false
 
-		@post = ~>
-			@wait = true
+		post() {
+			this.wait = true
 
 			files = if @files? and @files.length > 0
 				then @files.map (f) -> f.id
 				else undefined
 
-			@api \posts/create do
-				text: @refs.text.value
+			this.api 'posts/create' do
+				text: this.refs.text.value
 				media_ids: files
-				reply_to_id: if @opts.reply? then @opts.reply.id else undefined
-				poll: if @poll then @refs.poll.get! else undefined
-			.then (data) ~>
-				@trigger \post
-				@unmount!
-			.catch (err) ~>
+				reply_to_id: if this.opts.reply? then this.opts.reply.id else undefined
+				poll: if @poll then this.refs.poll.get! else undefined
+			.then (data) =>
+				this.trigger('post');
+				this.unmount();
+			.catch (err) =>
 				console.error err
-				#@opts.ui.trigger \notification 'Error!'
-				@wait = false
-				@update!
+				#this.opts.ui.trigger 'notification' 'Error!'
+				this.wait = false
+				this.update();
 
-		@cancel = ~>
-			@trigger \cancel
-			@unmount!
+		cancel() {
+			this.trigger('cancel');
+			this.unmount();
 
-		@cat = ~>
-			@refs.text.value = @refs.text.value + get-cat!
+		cat() {
+			this.refs.text.value = this.refs.text.value + get-cat!
 	</script>
 </mk-post-form>
diff --git a/src/web/app/mobile/tags/post-preview.tag b/src/web/app/mobile/tags/post-preview.tag
index d86ca86df..aa1d5f9b2 100644
--- a/src/web/app/mobile/tags/post-preview.tag
+++ b/src/web/app/mobile/tags/post-preview.tag
@@ -90,5 +90,5 @@
 							color #717171
 
 	</style>
-	<script>@post = @opts.post</script>
+	<script>this.post = this.opts.post</script>
 </mk-post-preview>
diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag
index 18d538c32..120df4140 100644
--- a/src/web/app/mobile/tags/search-posts.tag
+++ b/src/web/app/mobile/tags/search-posts.tag
@@ -7,24 +7,24 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@max = 30
-		@offset = 0
+		this.max = 30
+		this.offset = 0
 
-		@query = @opts.query
-		@with-media = @opts.with-media
+		this.query = this.opts.query
+		this.with-media = this.opts.with-media
 
-		@init = new Promise (res, rej) ~>
-			@api \posts/search do
+		this.init = new Promise (res, rej) =>
+			this.api 'posts/search' do
 				query: @query
-			.then (posts) ~>
+			.then (posts) =>
 				res posts
-				@trigger \loaded
+				this.trigger('loaded');
 
-		@more = ~>
+		more() {
 			@offset += @max
-			@api \posts/search do
+			this.api 'posts/search' do
 				query: @query
 				max: @max
 				offset: @offset
diff --git a/src/web/app/mobile/tags/search.tag b/src/web/app/mobile/tags/search.tag
index 3cca973a2..ab7ba4fd2 100644
--- a/src/web/app/mobile/tags/search.tag
+++ b/src/web/app/mobile/tags/search.tag
@@ -6,10 +6,10 @@
 
 	</style>
 	<script>
-		@query = @opts.query
+		this.query = this.opts.query
 
-		@on \mount ~>
-			@refs.posts.on \loaded ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			this.refs.posts.on('loaded', () => {
+				this.trigger('loaded');
 	</script>
 </mk-search>
diff --git a/src/web/app/mobile/tags/stream-indicator.tag b/src/web/app/mobile/tags/stream-indicator.tag
index d2ab34574..caa727dd8 100644
--- a/src/web/app/mobile/tags/stream-indicator.tag
+++ b/src/web/app/mobile/tags/stream-indicator.tag
@@ -27,27 +27,27 @@
 
 	</style>
 	<script>
-		@mixin \stream
+		this.mixin('stream');
 
-		@on \before-mount ~>
-			@state = @get-stream-state!
+		this.on('before-mount', () => {
+			this.state = @get-stream-state!
 
-			if @state == \connected
-				@root.style.opacity = 0
+			if @state == 'connected' 
+				this.root.style.opacity = 0
 
-		@stream-state-ev.on \connected ~>
-			@state = @get-stream-state!
-			@update!
-			set-timeout ~>
-				Velocity @root, {
+		@stream-state-ev.on('connected', () => {
+			this.state = @get-stream-state!
+			this.update();
+			setTimeout =>
+				Velocity this.root, {
 					opacity: 0
-				} 200ms \linear
+				} 200ms 'linear' 
 			, 1000ms
 
-		@stream-state-ev.on \closed ~>
-			@state = @get-stream-state!
-			@update!
-			Velocity @root, {
+		@stream-state-ev.on('closed', () => {
+			this.state = @get-stream-state!
+			this.update();
+			Velocity this.root, {
 				opacity: 1
 			} 0ms
 	</script>
diff --git a/src/web/app/mobile/tags/sub-post-content.tag b/src/web/app/mobile/tags/sub-post-content.tag
index 2256bb348..91bd5ac1d 100644
--- a/src/web/app/mobile/tags/sub-post-content.tag
+++ b/src/web/app/mobile/tags/sub-post-content.tag
@@ -28,17 +28,17 @@
 
 	</style>
 	<script>
-		@mixin \text
+		this.mixin('text');
 
-		@post = @opts.post
+		this.post = this.opts.post
 
-		@on \mount ~>
+		this.on('mount', () => {
 			if @post.text?
 				tokens = @analyze @post.text
-				@refs.text.innerHTML = @compile tokens, false
+				this.refs.text.innerHTML = @compile tokens, false
 
-				@refs.text.children.for-each (e) ~>
-					if e.tag-name == \MK-URL
+				this.refs.text.children.for-each (e) =>
+					if e.tag-name == 'MK-URL' 
 						riot.mount e
 	</script>
 </mk-sub-post-content>
diff --git a/src/web/app/mobile/tags/timeline-post-sub.tag b/src/web/app/mobile/tags/timeline-post-sub.tag
index 8ffe84bbc..5a944db73 100644
--- a/src/web/app/mobile/tags/timeline-post-sub.tag
+++ b/src/web/app/mobile/tags/timeline-post-sub.tag
@@ -97,5 +97,5 @@
 								font-size 80%
 
 	</style>
-	<script>@post = @opts.post</script>
+	<script>this.post = this.opts.post</script>
 </mk-timeline-post-sub>
diff --git a/src/web/app/mobile/tags/timeline-post.tag b/src/web/app/mobile/tags/timeline-post.tag
index 9ffa2c918..faa05ec7a 100644
--- a/src/web/app/mobile/tags/timeline-post.tag
+++ b/src/web/app/mobile/tags/timeline-post.tag
@@ -286,62 +286,62 @@
 
 	</style>
 	<script>
-		@mixin \api
-		@mixin \text
-		@mixin \get-post-summary
-		@mixin \open-post-form
+		this.mixin('api');
+		this.mixin('text');
+		this.mixin('get-post-summary');
+		this.mixin('open-post-form');
 
-		@post = @opts.post
-		@is-repost = @post.repost? and !@post.text?
-		@p = if @is-repost then @post.repost else @post
-		@summary = @get-post-summary @p
-		@url = CONFIG.url + '/' + @p.user.username + '/' + @p.id
+		this.post = this.opts.post
+		this.is-repost = @post.repost? and !@post.text?
+		this.p = if @is-repost then @post.repost else @post
+		this.summary = @get-post-summary @p
+		this.url = CONFIG.url + '/' + @p.user.username + '/' + @p.id
 
-		@on \mount ~>
+		this.on('mount', () => {
 			if @p.text?
 				tokens = if @p._highlight?
 					then @analyze @p._highlight
 					else @analyze @p.text
 
-				@refs.text.innerHTML = @refs.text.innerHTML.replace '<p class="dummy"></p>' if @p._highlight?
+				this.refs.text.innerHTML = this.refs.text.innerHTML.replace '<p class="dummy"></p>' if @p._highlight?
 					then @compile tokens, true, false
 					else @compile tokens
 
-				@refs.text.children.for-each (e) ~>
-					if e.tag-name == \MK-URL
+				this.refs.text.children.for-each (e) =>
+					if e.tag-name == 'MK-URL' 
 						riot.mount e
 
-				# URLをプレビュー
+				// URLをプレビュー
 				tokens
-					.filter (t) -> t.type == \link
-					.map (t) ~>
-						@preview = @refs.text.append-child document.create-element \mk-url-preview
+					.filter (t) -> t.type == 'link' 
+					.map (t) =>
+						this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
 						riot.mount @preview, do
 							url: t.content
 
-		@reply = ~>
+		reply() {
 			@open-post-form do
 				reply: @p
 
-		@repost = ~>
+		repost() {
 			text = window.prompt '「' + @summary + '」をRepost'
 			if text?
-				@api \posts/create do
+				this.api 'posts/create' do
 					repost_id: @p.id
 					text: if text == '' then undefined else text
 
-		@like = ~>
+		like() {
 			if @p.is_liked
-				@api \posts/likes/delete do
+				this.api 'posts/likes/delete' do
 					post_id: @p.id
-				.then ~>
+				.then =>
 					@p.is_liked = false
-					@update!
+					this.update();
 			else
-				@api \posts/likes/create do
+				this.api 'posts/likes/create' do
 					post_id: @p.id
-				.then ~>
+				.then =>
 					@p.is_liked = true
-					@update!
+					this.update();
 	</script>
 </mk-timeline-post>
diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag
index c41016076..156c4e429 100644
--- a/src/web/app/mobile/tags/timeline.tag
+++ b/src/web/app/mobile/tags/timeline.tag
@@ -74,45 +74,45 @@
 
 	</style>
 	<script>
-		@posts = []
-		@init = true
-		@fetching = false
-		@can-fetch-more = true
+		this.posts = []
+		this.init = true
+		this.fetching = false
+		this.can-fetch-more = true
 
-		@on \mount ~>
-			@opts.init.then (posts) ~>
-				@init = false
+		this.on('mount', () => {
+			this.opts.init.then (posts) =>
+				this.init = false
 				@set-posts posts
 
-		@on \update ~>
-			@posts.for-each (post) ~>
+		this.on('update', () => {
+			@posts.for-each (post) =>
 				date = (new Date post.created_at).get-date!
 				month = (new Date post.created_at).get-month! + 1
 				post._date = date
 				post._datetext = month + '月 ' + date + '日'
 
-		@more = ~>
+		more() {
 			if @init or @fetching or @posts.length == 0 then return
-			@fetching = true
-			@update!
-			@opts.more!.then (posts) ~>
-				@fetching = false
+			this.fetching = true
+			this.update();
+			this.opts.more!.then (posts) =>
+				this.fetching = false
 				@prepend-posts posts
 
-		@set-posts = (posts) ~>
-			@posts = posts
-			@update!
+		set-posts(posts) {
+			this.posts = posts
+			this.update();
 
-		@prepend-posts = (posts) ~>
-			posts.for-each (post) ~>
+		prepend-posts(posts) {
+			posts.for-each (post) =>
 				@posts.push post
-				@update!
+				this.update();
 
-		@add-post = (post) ~>
+		add-post(post) {
 			@posts.unshift post
-			@update!
+			this.update();
 
-		@tail = ~>
+		tail() {
 			@posts[@posts.length - 1]
 	</script>
 </mk-timeline>
diff --git a/src/web/app/mobile/tags/ui-header.tag b/src/web/app/mobile/tags/ui-header.tag
index d47c3610f..f4f44e972 100644
--- a/src/web/app/mobile/tags/ui-header.tag
+++ b/src/web/app/mobile/tags/ui-header.tag
@@ -88,17 +88,17 @@
 
 	</style>
 	<script>
-		@mixin \ui
-		@mixin \open-post-form
+		this.mixin('ui');
+		this.mixin('open-post-form');
 
-		@on \mount ~>
-			@opts.ready!
+		this.on('mount', () => {
+			this.opts.ready!
 
-		@ui.on \title (title) ~>
-			if @refs.title?
-				@refs.title.innerHTML = title
+		this.ui.on('title', (title) => {
+			if this.refs.title?
+				this.refs.title.innerHTML = title
 
-		@post = ~>
+		post() {
 			@open-post-form!
 	</script>
 </mk-ui-header>
diff --git a/src/web/app/mobile/tags/ui-nav.tag b/src/web/app/mobile/tags/ui-nav.tag
index a5dbd4cba..efdec8e14 100644
--- a/src/web/app/mobile/tags/ui-nav.tag
+++ b/src/web/app/mobile/tags/ui-nav.tag
@@ -117,14 +117,14 @@
 
 	</style>
 	<script>
-		@mixin \i
-		@mixin \page
+		this.mixin('i');
+		this.mixin('page');
 
-		@on \mount ~>
-			@opts.ready!
+		this.on('mount', () => {
+			this.opts.ready!
 
-		@search = ~>
-			query = window.prompt \検索
+		search() {
+			query = window.prompt '検索' 
 			if query? and query != ''
 				@page '/search:' + query
 	</script>
diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag
index c3ffe9097..cb87469c0 100644
--- a/src/web/app/mobile/tags/ui.tag
+++ b/src/web/app/mobile/tags/ui.tag
@@ -14,37 +14,37 @@
 					background #fff
 	</style>
 	<script>
-		@mixin \stream
+		this.mixin('stream');
 
-		@ready-count = 0
-		@is-drawer-opening = false
+		this.ready-count = 0
+		this.is-drawer-opening = false
 
-		#@ui.on \notification (text) ~>
-		#	alert text
+		#this.ui.on('notification', (text) => {
+		// alert text
 
-		@on \mount ~>
-			@stream.on \notification @on-stream-notification
+		this.on('mount', () => {
+			@stream.on 'notification' this.on-stream-notification
 			@ready!
 
-		@on \unmount ~>
-			@stream.off \notification @on-stream-notification
+		this.on('unmount', () => {
+			@stream.off 'notification' this.on-stream-notification
 
-		@ready = ~>
+		ready() {
 			@ready-count++
 
 			if @ready-count == 2
 				@init-view-position!
 
-		@init-view-position = ~>
-			top = @refs.header.root.offset-height
-			@refs.main.style.padding-top = top + \px
+		init-view-position() {
+			top = this.refs.header.root.offset-height
+			this.refs.main.style.padding-top = top + 'px' 
 
-		@toggle-drawer = ~>
-			@is-drawer-opening = !@is-drawer-opening
-			@refs.nav.root.style.display = if @is-drawer-opening then \block else \none
+		toggle-drawer() {
+			this.is-drawer-opening = !@is-drawer-opening
+			this.refs.nav.root.style.display = if @is-drawer-opening then 'block' else 'none' 
 
-		@on-stream-notification = (notification) ~>
-			el = document.body.append-child document.create-element \mk-notify
+		on-stream-notification(notification) {
+			el = document.body.appendChild document.createElement 'mk-notify' 
 			riot.mount el, do
 				notification: notification
 	</script>
diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag
index f328ab61d..49091421e 100644
--- a/src/web/app/mobile/tags/user-followers.tag
+++ b/src/web/app/mobile/tags/user-followers.tag
@@ -6,20 +6,20 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@fetch = (iknow, limit, cursor, cb) ~>
-			@api \users/followers do
+		fetch(iknow, limit, cursor, cb) {
+			this.api 'users/followers' do
 				user_id: @user.id
 				iknow: iknow
 				limit: limit
 				cursor: if cursor? then cursor else undefined
 			.then cb
 
-		@on \mount ~>
-			@refs.list.on \loaded ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			this.refs.list.on('loaded', () => {
+				this.trigger('loaded');
 	</script>
 </mk-user-followers>
diff --git a/src/web/app/mobile/tags/user-following.tag b/src/web/app/mobile/tags/user-following.tag
index 29f3680b6..c00894a4c 100644
--- a/src/web/app/mobile/tags/user-following.tag
+++ b/src/web/app/mobile/tags/user-following.tag
@@ -6,20 +6,20 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@user = @opts.user
+		this.user = this.opts.user
 
-		@fetch = (iknow, limit, cursor, cb) ~>
-			@api \users/following do
+		fetch(iknow, limit, cursor, cb) {
+			this.api 'users/following' do
 				user_id: @user.id
 				iknow: iknow
 				limit: limit
 				cursor: if cursor? then cursor else undefined
 			.then cb
 
-		@on \mount ~>
-			@refs.list.on \loaded ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			this.refs.list.on('loaded', () => {
+				this.trigger('loaded');
 	</script>
 </mk-user-following>
diff --git a/src/web/app/mobile/tags/user-preview.tag b/src/web/app/mobile/tags/user-preview.tag
index 2e600a817..09cfeb49e 100644
--- a/src/web/app/mobile/tags/user-preview.tag
+++ b/src/web/app/mobile/tags/user-preview.tag
@@ -85,5 +85,5 @@
 						color #717171
 
 	</style>
-	<script>@user = @opts.user</script>
+	<script>this.user = this.opts.user</script>
 </mk-user-preview>
diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag
index 9646dda9e..a05fd8422 100644
--- a/src/web/app/mobile/tags/user-timeline.tag
+++ b/src/web/app/mobile/tags/user-timeline.tag
@@ -9,23 +9,23 @@
 
 	</style>
 	<script>
-		@mixin \api
+		this.mixin('api');
 
-		@user = @opts.user
-		@with-media = @opts.with-media
+		this.user = this.opts.user
+		this.with-media = this.opts.with-media
 
-		@init = new Promise (res, rej) ~>
-			@api \users/posts do
+		this.init = new Promise (res, rej) =>
+			this.api 'users/posts' do
 				user_id: @user.id
 				with_media: @with-media
-			.then (posts) ~>
+			.then (posts) =>
 				res posts
-				@trigger \loaded
+				this.trigger('loaded');
 
-		@more = ~>
-			@api \users/posts do
+		more() {
+			this.api 'users/posts' do
 				user_id: @user.id
 				with_media: @with-media
-				max_id: @refs.timeline.tail!.id
+				max_id: this.refs.timeline.tail!.id
 	</script>
 </mk-user-timeline>
diff --git a/src/web/app/mobile/tags/user.tag b/src/web/app/mobile/tags/user.tag
index 37900bb61..6cd815a37 100644
--- a/src/web/app/mobile/tags/user.tag
+++ b/src/web/app/mobile/tags/user.tag
@@ -154,38 +154,38 @@
 
 	</style>
 	<script>
-		@age = require \s-age
+		this.age = require 's-age' 
 
-		@mixin \i
-		@mixin \api
+		this.mixin('i');
+		this.mixin('api');
 
-		@username = @opts.user
-		@page = if @opts.page? then @opts.page else \posts
-		@fetching = true
+		this.username = this.opts.user
+		this.page = if this.opts.page? then this.opts.page else 'posts' 
+		this.fetching = true
 
-		@on \mount ~>
-			@api \users/show do
+		this.on('mount', () => {
+			this.api 'users/show' do
 				username: @username
-			.then (user) ~>
-				@fetching = false
-				@user = user
-				@trigger \loaded user
-				@update!
+			.then (user) =>
+				this.fetching = false
+				this.user = user
+				this.trigger 'loaded' user
+				this.update();
 
-		@go-posts = ~>
-			@page = \posts
-			@update!
+		go-posts() {
+			this.page = 'posts' 
+			this.update();
 
-		@go-media = ~>
-			@page = \media
-			@update!
+		go-media() {
+			this.page = 'media' 
+			this.update();
 
-		@go-graphs = ~>
-			@page = \graphs
-			@update!
+		go-graphs() {
+			this.page = 'graphs' 
+			this.update();
 
-		@go-likes = ~>
-			@page = \likes
-			@update!
+		go-likes() {
+			this.page = 'likes' 
+			this.update();
 	</script>
 </mk-user>
diff --git a/src/web/app/mobile/tags/users-list.tag b/src/web/app/mobile/tags/users-list.tag
index a45d2a9e0..6d45c32c3 100644
--- a/src/web/app/mobile/tags/users-list.tag
+++ b/src/web/app/mobile/tags/users-list.tag
@@ -70,44 +70,44 @@
 
 	</style>
 	<script>
-		@mixin \i
+		this.mixin('i');
 
-		@limit = 30users
-		@mode = \all
+		this.limit = 30users
+		this.mode = 'all' 
 
-		@fetching = true
-		@more-fetching = false
+		this.fetching = true
+		this.more-fetching = false
 
-		@on \mount ~>
-			@fetch ~>
-				@trigger \loaded
+		this.on('mount', () => {
+			@fetch =>
+				this.trigger('loaded');
 
-		@fetch = (cb) ~>
-			@fetching = true
-			@update!
-			obj <~ @opts.fetch do
-				@mode == \iknow
+		fetch(cb) {
+			this.fetching = true
+			this.update();
+			obj <~ this.opts.fetch do
+				@mode == 'iknow' 
 				@limit
 				null
-			@users = obj.users
-			@next = obj.next
-			@fetching = false
-			@update!
+			this.users = obj.users
+			this.next = obj.next
+			this.fetching = false
+			this.update();
 			if cb? then cb!
 
-		@more = ~>
-			@more-fetching = true
-			@update!
-			obj <~ @opts.fetch do
-				@mode == \iknow
+		more() {
+			this.more-fetching = true
+			this.update();
+			obj <~ this.opts.fetch do
+				@mode == 'iknow' 
 				@limit
 				@cursor
-			@users = @users.concat obj.users
-			@next = obj.next
-			@more-fetching = false
-			@update!
+			this.users = @users.concat obj.users
+			this.next = obj.next
+			this.more-fetching = false
+			this.update();
 
-		@set-mode = (mode) ~>
+		set-mode(mode) {
 			@update do
 				mode: mode
 

From 3c3040783f9f52f7e8a8e37a25cff7f97ef1ecd2 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 10:04:11 +0900
Subject: [PATCH 02/32] wip

---
 src/web/app/common/tags/file-type-icon.tag    |  2 +-
 src/web/app/common/tags/messaging/form.tag    | 25 ++++++++------
 src/web/app/common/tags/messaging/index.tag   | 34 +++++++++----------
 src/web/app/common/tags/messaging/message.tag |  2 +-
 src/web/app/common/tags/messaging/room.tag    |  8 ++---
 src/web/app/common/tags/uploader.tag          |  2 +-
 src/web/app/desktop/tags/donation.tag         |  6 ++--
 .../desktop/tags/drive/file-contextmenu.tag   |  6 ++--
 .../app/desktop/tags/home-widgets/profile.tag |  4 +--
 .../desktop/tags/home-widgets/timeline.tag    |  2 +-
 src/web/app/desktop/tags/home.tag             |  2 +-
 src/web/app/desktop/tags/pages/home.tag       |  2 +-
 .../desktop/tags/set-avatar-suggestion.tag    |  2 +-
 .../desktop/tags/set-banner-suggestion.tag    |  2 +-
 src/web/app/desktop/tags/settings.tag         | 14 ++++----
 src/web/app/desktop/tags/user-header.tag      |  4 +--
 src/web/app/mobile/tags/page/home.tag         |  2 +-
 17 files changed, 60 insertions(+), 59 deletions(-)

diff --git a/src/web/app/common/tags/file-type-icon.tag b/src/web/app/common/tags/file-type-icon.tag
index c484a5749..55c473bcd 100644
--- a/src/web/app/common/tags/file-type-icon.tag
+++ b/src/web/app/common/tags/file-type-icon.tag
@@ -5,6 +5,6 @@
 			display inline
 	</style>
 	<script>
-		this.kind = this.opts.type.split '/' .0
+		this.kind = this.opts.type.split('/')[0];
 	</script>
 </mk-file-type-icon>
diff --git a/src/web/app/common/tags/messaging/form.tag b/src/web/app/common/tags/messaging/form.tag
index 649c16a25..4ae1706ff 100644
--- a/src/web/app/common/tags/messaging/form.tag
+++ b/src/web/app/common/tags/messaging/form.tag
@@ -150,23 +150,26 @@
 			event.one('selected', files => {
 				files.forEach(this.addFile);
 			});
+		}
 
 		send() {
-			this.sending = true
-			this.api 'messaging/messages/create' do
-				user_id: this.opts.user.id
+			this.sending = true;
+			this.api('messaging/messages/create', {
+				user_id: this.opts.user.id,
 				text: this.refs.text.value
-			.then (message) =>
-				@clear!
-			.catch (err) =>
-				console.error err
-			.then =>
-				this.sending = false
+			}).then(message => {
+				this.clear();
+			}).catch(err => {
+				console.error(err);
+			}).then(() => {
+				this.sending = false;
 				this.update();
+			});
 
 		clear() {
-			this.refs.text.value = ''
-			this.files = []
+			this.refs.text.value = '';
+			this.files = [];
 			this.update();
+		}
 	</script>
 </mk-messaging-form>
diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
index f9ce48641..d49596c87 100644
--- a/src/web/app/common/tags/messaging/index.tag
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -289,29 +289,27 @@
 		this.mixin('i');
 		this.mixin('api');
 
-		this.search-result = []
+		this.searchResult = [];
 
 		this.on('mount', () => {
-			this.api 'messaging/history' 
-			.then (history) =>
-				this.is-loading = false
-				history.for-each (message) =>
-					message.is_me = message.user_id == @I.id
-					message._click = =>
-						if message.is_me
-							this.trigger 'navigate-user' message.recipient
-						else
-							this.trigger 'navigate-user' message.user
-				this.history = history
+			this.api('messaging/history').then(history => {
+				this.isLoading = false;
+				history.forEach(message => {
+					message.is_me = message.user_id == this.I.id
+					message._click = () => {
+						this.trigger('navigate-user', message.is_me ? message.recipient : message.user);
+					};
+				});
+				this.history = history;
 				this.update();
-			.catch (err) =>
-				console.error err
+			});
+		}
 
 		search() {
-			q = this.refs.search.value
-			if q == ''
-				this.search-result = []
-			else
+			const q = this.refs.search.value;
+			if (q == '') {
+				this.searchResult = [];
+			} else {
 				this.api 'users/search' do
 					query: q
 					max: 5
diff --git a/src/web/app/common/tags/messaging/message.tag b/src/web/app/common/tags/messaging/message.tag
index a43991e0e..96b4e8daf 100644
--- a/src/web/app/common/tags/messaging/message.tag
+++ b/src/web/app/common/tags/messaging/message.tag
@@ -207,7 +207,7 @@
 		this.mixin('text');
 
 		this.message = this.opts.message
-		@message.is_me = @message.user.id == @I.id
+		@message.is_me = @message.user.id == this.I.id
 
 		this.on('mount', () => {
 			if @message.text?
diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index a571b330c..320af8a8b 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -133,7 +133,7 @@
 		this.sending = false
 		this.messages = []
 
-		this.connection = new @MessagingStreamConnection @I, @user.id
+		this.connection = new @MessagingStreamConnection this.I, @user.id
 
 		this.on('mount', () => {
 			@connection.event.on 'message' this.on-message
@@ -169,7 +169,7 @@
 			is-bottom = @is-bottom!
 
 			@messages.push message
-			if message.user_id != @I.id and not document.hidden
+			if message.user_id != this.I.id and not document.hidden
 				@connection.socket.send JSON.stringify do
 					type: 'read' 
 					id: message.id
@@ -178,7 +178,7 @@
 			if is-bottom
 				// Scroll to bottom
 				@scroll-to-bottom!
-			else if message.user_id != @I.id
+			else if message.user_id != this.I.id
 				// Notify
 				@notify '新しいメッセージがあります'
 
@@ -216,7 +216,7 @@
 		on-visibilitychange() {
 			if document.hidden then return
 			@messages.for-each (message) =>
-				if message.user_id != @I.id and not message.is_read
+				if message.user_id != this.I.id and not message.is_read
 					@connection.socket.send JSON.stringify do
 						type: 'read' 
 						id: message.id
diff --git a/src/web/app/common/tags/uploader.tag b/src/web/app/common/tags/uploader.tag
index 2cf1aa324..72f6eaa22 100644
--- a/src/web/app/common/tags/uploader.tag
+++ b/src/web/app/common/tags/uploader.tag
@@ -164,7 +164,7 @@
 			reader.read-as-data-URL file
 
 			data = new FormData!
-			data.append 'i' @I.token
+			data.append 'i' this.I.token
 			data.append 'file' file
 
 			if folder?
diff --git a/src/web/app/desktop/tags/donation.tag b/src/web/app/desktop/tags/donation.tag
index d92e24e30..b01c0a44d 100644
--- a/src/web/app/desktop/tags/donation.tag
+++ b/src/web/app/desktop/tags/donation.tag
@@ -54,11 +54,11 @@
 			e.prevent-default!
 			e.stop-propagation!
 
-			@I.data.no_donation = true
-			@I.update!
+			this.I.data.no_donation = true
+			this.I.update!
 			this.api 'i/appdata/set' do
 				data: JSON.stringify do
-					no_donation: @I.data.no_donation
+					no_donation: this.I.data.no_donation
 
 			this.unmount();
 
diff --git a/src/web/app/desktop/tags/drive/file-contextmenu.tag b/src/web/app/desktop/tags/drive/file-contextmenu.tag
index 69073bd29..5919599be 100644
--- a/src/web/app/desktop/tags/drive/file-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/file-contextmenu.tag
@@ -81,15 +81,15 @@
 
 		set-avatar() {
 			this.refs.ctx.close!
-			@update-avatar @I, null, @file
+			@update-avatar this.I, null, @file
 
 		set-banner() {
 			this.refs.ctx.close!
-			@update-banner @I, null, @file
+			@update-banner this.I, null, @file
 
 		set-wallpaper() {
 			this.refs.ctx.close!
-			@update-wallpaper @I, null, @file
+			@update-wallpaper this.I, null, @file
 
 		add-app() {
 			@NotImplementedException!
diff --git a/src/web/app/desktop/tags/home-widgets/profile.tag b/src/web/app/desktop/tags/home-widgets/profile.tag
index d8d1f6107..3cff6b682 100644
--- a/src/web/app/desktop/tags/home-widgets/profile.tag
+++ b/src/web/app/desktop/tags/home-widgets/profile.tag
@@ -47,9 +47,9 @@
 		this.mixin('update-banner');
 
 		set-avatar() {
-			@update-avatar @I
+			@update-avatar this.I
 
 		set-banner() {
-			@update-banner @I
+			@update-banner this.I
 	</script>
 </mk-profile-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index 10918b5e0..1fcf4ab57 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -39,7 +39,7 @@
 		this.is-loading = true
 		this.is-empty = false
 		this.more-loading = false
-		this.no-following = @I.following_count == 0
+		this.no-following = this.I.following_count == 0
 
 		this.on('mount', () => {
 			@stream.on 'post' this.on-stream-post
diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag
index 182f557b7..729022073 100644
--- a/src/web/app/desktop/tags/home.tag
+++ b/src/web/app/desktop/tags/home.tag
@@ -70,7 +70,7 @@
 			this.refs.tl.on('loaded', () => {
 				this.trigger('loaded');
 
-			@I.data.home.for-each (widget) =>
+			this.I.data.home.for-each (widget) =>
 				try
 					el = document.createElement 'mk-' + widget.name + '-home-widget' 
 					switch widget.place
diff --git a/src/web/app/desktop/tags/pages/home.tag b/src/web/app/desktop/tags/pages/home.tag
index 348762d2d..0f0bc4e37 100644
--- a/src/web/app/desktop/tags/pages/home.tag
+++ b/src/web/app/desktop/tags/pages/home.tag
@@ -35,7 +35,7 @@
 			document.remove-event-listener 'visibilitychange' @window-on-visibilitychange
 
 		on-stream-post(post) {
-			if document.hidden and post.user_id !== @I.id
+			if document.hidden and post.user_id !== this.I.id
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
diff --git a/src/web/app/desktop/tags/set-avatar-suggestion.tag b/src/web/app/desktop/tags/set-avatar-suggestion.tag
index 858838743..149144edf 100644
--- a/src/web/app/desktop/tags/set-avatar-suggestion.tag
+++ b/src/web/app/desktop/tags/set-avatar-suggestion.tag
@@ -35,7 +35,7 @@
 		this.mixin('update-avatar');
 
 		set() {
-			@update-avatar @I
+			@update-avatar this.I
 
 		close(e) {
 			e.prevent-default!
diff --git a/src/web/app/desktop/tags/set-banner-suggestion.tag b/src/web/app/desktop/tags/set-banner-suggestion.tag
index 2a4ba8dbb..a1e9eb4ed 100644
--- a/src/web/app/desktop/tags/set-banner-suggestion.tag
+++ b/src/web/app/desktop/tags/set-banner-suggestion.tag
@@ -35,7 +35,7 @@
 		this.mixin('update-banner');
 
 		set() {
-			@update-banner @I
+			@update-banner this.I
 
 		close(e) {
 			e.prevent-default!
diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag
index 16369c2f4..e67a1b11a 100644
--- a/src/web/app/desktop/tags/settings.tag
+++ b/src/web/app/desktop/tags/settings.tag
@@ -209,7 +209,7 @@
 			this.page = page
 
 		avatar() {
-			@update-avatar @I
+			@update-avatar this.I
 
 		update-account() {
 			this.api 'i/update' do
@@ -223,21 +223,21 @@
 				console.error err
 
 		update-cache() {
-			@I.data.cache = !@I.data.cache
+			this.I.data.cache = !this.I.data.cache
 			this.api 'i/appdata/set' do
 				data: JSON.stringify do
-					cache: @I.data.cache
+					cache: this.I.data.cache
 
 		update-debug() {
-			@I.data.debug = !@I.data.debug
+			this.I.data.debug = !this.I.data.debug
 			this.api 'i/appdata/set' do
 				data: JSON.stringify do
-					debug: @I.data.debug
+					debug: this.I.data.debug
 
 		update-nya() {
-			@I.data.nya = !@I.data.nya
+			this.I.data.nya = !this.I.data.nya
 			this.api 'i/appdata/set' do
 				data: JSON.stringify do
-					nya: @I.data.nya
+					nya: this.I.data.nya
 	</script>
 </mk-settings>
diff --git a/src/web/app/desktop/tags/user-header.tag b/src/web/app/desktop/tags/user-header.tag
index dc7abb512..a2ed28b4f 100644
--- a/src/web/app/desktop/tags/user-header.tag
+++ b/src/web/app/desktop/tags/user-header.tag
@@ -132,10 +132,10 @@
 				this.refs.banner.style.filter = 'blur(' + blur + 'px)'
 
 		on-update-banner() {
-			if not @SIGNIN or @I.id != @user.id
+			if not @SIGNIN or this.I.id != @user.id
 				return
 
-			@update-banner @I, (i) =>
+			@update-banner this.I, (i) =>
 				@user.banner_url = i.banner_url
 				this.update();
 	</script>
diff --git a/src/web/app/mobile/tags/page/home.tag b/src/web/app/mobile/tags/page/home.tag
index db87483a9..cfa6d55da 100644
--- a/src/web/app/mobile/tags/page/home.tag
+++ b/src/web/app/mobile/tags/page/home.tag
@@ -33,7 +33,7 @@
 			document.remove-event-listener 'visibilitychange' @window-on-visibilitychange
 
 		on-stream-post(post) {
-			if document.hidden and post.user_id !== @I.id
+			if document.hidden and post.user_id !== this.I.id
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 

From 77914317171b55e5861cc6dd50d41e5bb3b4df38 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 10:27:44 +0900
Subject: [PATCH 03/32] wip

---
 src/web/app/common/tags/authorized-apps.tag   | 15 ++--
 src/web/app/common/tags/copyright.tag         |  8 +-
 src/web/app/common/tags/core-error.tag        |  3 +-
 src/web/app/common/tags/ellipsis.tag          |  5 --
 src/web/app/common/tags/introduction.tag      |  4 -
 src/web/app/common/tags/messaging/index.tag   | 26 +++---
 src/web/app/common/tags/messaging/room.tag    |  4 +-
 src/web/app/common/tags/number.tag            | 13 +--
 src/web/app/common/tags/poll-editor.tag       | 19 ++--
 src/web/app/common/tags/poll.tag              | 47 +++++-----
 src/web/app/common/tags/signin-history.tag    |  4 +-
 src/web/app/common/tags/signin.tag            |  6 +-
 src/web/app/common/tags/signup.tag            | 27 +++---
 src/web/app/common/tags/special-message.tag   |  6 +-
 src/web/app/common/tags/url-preview.tag       | 26 +++---
 src/web/app/common/tags/url.tag               | 19 ++--
 .../desktop/tags/autocomplete-suggestion.tag  | 22 ++---
 src/web/app/desktop/tags/contextmenu.tag      |  8 +-
 src/web/app/desktop/tags/donation.tag         |  4 +-
 .../desktop/tags/drive/base-contextmenu.tag   |  6 +-
 src/web/app/desktop/tags/drive/browser.tag    | 90 +++++++++----------
 .../desktop/tags/drive/file-contextmenu.tag   | 10 +--
 src/web/app/desktop/tags/drive/file.tag       | 42 ++++-----
 .../desktop/tags/drive/folder-contextmenu.tag | 12 +--
 src/web/app/desktop/tags/drive/folder.tag     | 52 +++++------
 src/web/app/desktop/tags/drive/nav-folder.tag | 40 ++++-----
 src/web/app/desktop/tags/input-dialog.tag     |  4 +-
 src/web/app/desktop/tags/post-form.tag        | 30 +++----
 .../tags/select-file-from-drive-window.tag    |  2 +-
 .../desktop/tags/set-avatar-suggestion.tag    |  4 +-
 .../desktop/tags/set-banner-suggestion.tag    |  4 +-
 src/web/app/desktop/tags/timeline-post.tag    |  2 +-
 .../app/desktop/tags/ui-header-account.tag    |  6 +-
 .../desktop/tags/ui-header-notifications.tag  |  6 +-
 src/web/app/desktop/tags/ui-header-search.tag |  2 +-
 src/web/app/desktop/tags/ui.tag               |  2 +-
 src/web/app/desktop/tags/window.tag           | 24 ++---
 src/web/app/dev/tags/new-app-form.tag         |  2 +-
 src/web/app/mobile/tags/drive-selector.tag    |  2 +-
 src/web/app/mobile/tags/drive.tag             | 38 ++++----
 src/web/app/mobile/tags/drive/file-viewer.tag | 14 +--
 src/web/app/mobile/tags/drive/file.tag        | 10 +--
 src/web/app/mobile/tags/drive/folder.tag      |  2 +-
 src/web/app/mobile/tags/post-form.tag         | 12 +--
 44 files changed, 344 insertions(+), 340 deletions(-)

diff --git a/src/web/app/common/tags/authorized-apps.tag b/src/web/app/common/tags/authorized-apps.tag
index 918e8b956..14795e49d 100644
--- a/src/web/app/common/tags/authorized-apps.tag
+++ b/src/web/app/common/tags/authorized-apps.tag
@@ -19,16 +19,15 @@
 	<script>
 		this.mixin('api');
 
-		this.apps = []
-		this.fetching = true
+		this.apps = [];
+		this.fetching = true;
 
 		this.on('mount', () => {
-			this.api 'i/authorized_apps' 
-			.then (apps) =>
-				this.apps = apps
-				this.fetching = false
+			this.api('i/authorized_apps').then(apps => {
+				this.apps = apps;
+				this.fetching = false;
 				this.update();
-			.catch (err) =>
-				console.error err
+			});
+		});
 	</script>
 </mk-authorized-apps>
diff --git a/src/web/app/common/tags/copyright.tag b/src/web/app/common/tags/copyright.tag
index 368c4e319..9c3f1f648 100644
--- a/src/web/app/common/tags/copyright.tag
+++ b/src/web/app/common/tags/copyright.tag
@@ -1,11 +1,7 @@
-<mk-copyright><span>(c) syuilo 2014-2017</span>
+<mk-copyright>
+	<span>(c) syuilo 2014-2017</span>
 	<style>
 		:scope
 			display block
-
-			
-
-			
-
 	</style>
 </mk-copyright>
diff --git a/src/web/app/common/tags/core-error.tag b/src/web/app/common/tags/core-error.tag
index 07f41e403..b424c8abb 100644
--- a/src/web/app/common/tags/core-error.tag
+++ b/src/web/app/common/tags/core-error.tag
@@ -59,6 +59,7 @@
 	<script>
 		retry() {
 			this.unmount();
-			this.opts.retry!
+			this.opts.retry();
+		}
 	</script>
 </mk-core-error>
diff --git a/src/web/app/common/tags/ellipsis.tag b/src/web/app/common/tags/ellipsis.tag
index 58f108395..97ef745d0 100644
--- a/src/web/app/common/tags/ellipsis.tag
+++ b/src/web/app/common/tags/ellipsis.tag
@@ -20,10 +20,5 @@
 					opacity 1
 				40%
 					opacity 0
-
-			
-
-			
-
 	</style>
 </mk-ellipsis>
diff --git a/src/web/app/common/tags/introduction.tag b/src/web/app/common/tags/introduction.tag
index 24fe86e99..fda011eff 100644
--- a/src/web/app/common/tags/introduction.tag
+++ b/src/web/app/common/tags/introduction.tag
@@ -21,9 +21,5 @@
 					margin 0
 					text-align center
 
-			
-
-			
-
 	</style>
 </mk-introduction>
diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
index d49596c87..e9a031a2b 100644
--- a/src/web/app/common/tags/messaging/index.tag
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -327,29 +327,29 @@
 			key = e.which
 			switch (key)
 				| 9, 40 => // Key[TAB] or Key[↓]
-					e.prevent-default!
-					e.stop-propagation!
-					this.refs.search-result.child-nodes[0].focus();
+					e.preventDefault();
+					e.stopPropagation();
+					this.refs.search-result.childNodes[0].focus();
 
 		on-search-result-keydown(i, e) {
 			key = e.which
 			switch (key)
 				| 10, 13 => // Key[ENTER]
-					e.prevent-default!
-					e.stop-propagation!
+					e.preventDefault();
+					e.stopPropagation();
 					@search-result[i]._click!
 				| 27 => // Key[ESC]
-					e.prevent-default!
-					e.stop-propagation!
+					e.preventDefault();
+					e.stopPropagation();
 					this.refs.search.focus();
 				| 38 => // Key[↑]
-					e.prevent-default!
-					e.stop-propagation!
-					(this.refs.search-result.child-nodes[i].previous-element-sibling || this.refs.search-result.child-nodes[@search-result.length - 1]).focus();
+					e.preventDefault();
+					e.stopPropagation();
+					(this.refs.search-result.childNodes[i].previous-element-sibling || this.refs.search-result.childNodes[@search-result.length - 1]).focus();
 				| 9, 40 => // Key[TAB] or Key[↓]
-					e.prevent-default!
-					e.stop-propagation!
-					(this.refs.search-result.child-nodes[i].next-element-sibling || this.refs.search-result.child-nodes[0]).focus();
+					e.preventDefault();
+					e.stopPropagation();
+					(this.refs.search-result.childNodes[i].next-element-sibling || this.refs.search-result.childNodes[0]).focus();
 
 	</script>
 </mk-messaging>
diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index 320af8a8b..a40258569 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -203,13 +203,13 @@
 			n.inner-HTML = '<i class="fa fa-arrow-circle-down"></i>' + message
 			n.onclick = =>
 				@scroll-to-bottom!
-				n.parent-node.remove-child n
+				n.parentNode.removeChild n
 			this.refs.notifications.appendChild n
 
 			setTimeout =>
 				n.style.opacity = 0
 				setTimeout =>
-					n.parent-node.remove-child n
+					n.parentNode.removeChild n
 				, 1000ms
 			, 4000ms
 
diff --git a/src/web/app/common/tags/number.tag b/src/web/app/common/tags/number.tag
index 626b184fc..212a80b73 100644
--- a/src/web/app/common/tags/number.tag
+++ b/src/web/app/common/tags/number.tag
@@ -6,13 +6,14 @@
 	</style>
 	<script>
 		this.on('mount', () => {
-			// バグ? https://github.com/riot/riot/issues/2103
-			#value = this.opts.value
-			value = this.opts.riot-value
-			max = this.opts.max
+			// https://github.com/riot/riot/issues/2103
+			//value = this.opts.value
+			const value = this.opts.riotValue;
+			const max = this.opts.max;
 
-			if max? then if value > max then value = max
+			if (max != null && value > max) value = max;
 
-			this.root.innerHTML = value.to-locale-string!
+			this.root.innerHTML = value.toLocaleString();
+		});
 	</script>
 </mk-number>
diff --git a/src/web/app/common/tags/poll-editor.tag b/src/web/app/common/tags/poll-editor.tag
index 46975bbe2..e35d8e136 100644
--- a/src/web/app/common/tags/poll-editor.tag
+++ b/src/web/app/common/tags/poll-editor.tag
@@ -86,26 +86,31 @@
 
 	</style>
 	<script>
-		this.choices = ['', '']
+		this.choices = ['', ''];
 
 		oninput(i, e) {
-			@choices[i] = e.target.value
+			this.choices[i] = e.target.value;
+		}
 
 		add() {
-			@choices.push ''
+			this.choices.push('');
 			this.update();
-			this.refs.choices.child-nodes[@choices.length - 1].child-nodes[0].focus();
+			this.refs.choices.childNodes[this.choices.length - 1].childNodes[0].focus();
+		}
 
 		remove(i) {
-			this.choices = @choices.filter((_, _i) -> _i != i)
+			this.choices = this.choices.filter((_, _i) => _i != i);
 			this.update();
+		}
 
 		destroy() {
-			this.opts.ondestroy!
+			this.opts.ondestroy();
+		}
 
 		get() {
 			return {
-				choices: @choices.filter (choice) -> choice != ''
+				choices: this.choices.filter(choice => choice != '')
 			}
+		}
 	</script>
 </mk-poll-editor>
diff --git a/src/web/app/common/tags/poll.tag b/src/web/app/common/tags/poll.tag
index d0ee1fad7..c9209c3a3 100644
--- a/src/web/app/common/tags/poll.tag
+++ b/src/web/app/common/tags/poll.tag
@@ -70,30 +70,35 @@
 	<script>
 		this.mixin('api');
 
-		this.post = this.opts.post
-		this.poll = @post.poll
-		this.total = @poll.choices.reduce ((a, b) -> a + b.votes), 0
-		this.is-voted = @poll.choices.some (c) -> c.is_voted
-		this.result = @is-voted
+		this.post = this.opts.post;
+		this.poll = this.post.poll;
+		this.total = this.poll.choices.reduce((a, b) => a + b.votes, 0);
+		this.isVoted = this.poll.choices.some(c => c.is_voted);
+		this.result = this.isVoted;
 
-		toggle-result() {
-			this.result = !@result
+		toggleResult() {
+			this.result = !this.result;
+		}
 
 		vote(id) {
-			if (@poll.choices.some (c) -> c.is_voted) then return
-			this.api 'posts/polls/vote' do
-				post_id: @post.id
+			if (this.poll.choices.some(c => c.is_voted)) return;
+			this.api('posts/polls/vote', {
+				post_id: this.post.id,
 				choice: id
-			.then =>
-				@poll.choices.for-each (c) ->
-					if c.id == id
-						c.votes++
-						c.is_voted = true
-				@update do
-					poll: @poll
-					is-voted: true
-					result: true
-					total: @total + 1
-
+			}).then(() => {
+				this.poll.choices.forEach(c => {
+					if (c.id == id) {
+						c.votes++;
+						c.is_voted = true;
+					}
+				});
+				this.update({
+					poll: this.poll,
+					isVoted: true,
+					result: true,
+					total: this.total + 1
+				});
+			});
+		}
 	</script>
 </mk-poll>
diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag
index 2b8bddd26..4b5c844b7 100644
--- a/src/web/app/common/tags/signin-history.tag
+++ b/src/web/app/common/tags/signin-history.tag
@@ -51,8 +51,8 @@
 		this.mixin('api');
 		this.mixin('stream');
 
-		this.history = []
-		this.fetching = true
+		this.history = [];
+		this.fetching = true;
 
 		this.on('mount', () => {
 			this.api 'i/signin_history' 
diff --git a/src/web/app/common/tags/signin.tag b/src/web/app/common/tags/signin.tag
index 75fa51afa..5cb63685f 100644
--- a/src/web/app/common/tags/signin.tag
+++ b/src/web/app/common/tags/signin.tag
@@ -99,8 +99,8 @@
 	<script>
 		this.mixin('api');
 
-		this.user = null
-		this.signing = false
+		this.user = null;
+		this.signing = false;
 
 		oninput() {
 			this.api 'users/show' do
@@ -111,7 +111,7 @@
 				this.update();
 
 		onsubmit(e) {
-			e.prevent-default!
+			e.preventDefault();
 
 			if this.refs.username.value == ''
 				this.refs.username.focus();
diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag
index 86c4bb5e1..55b1b7613 100644
--- a/src/web/app/common/tags/signup.tag
+++ b/src/web/app/common/tags/signup.tag
@@ -177,24 +177,27 @@
 		this.mixin('api');
 		this.mixin('get-password-strength');
 
-		this.username-state = null
-		this.password-strength = ''
-		this.password-retype-state = null
-		this.recaptchaed = false
+		this.usernameState = null;
+		this.passwordStrength = '';
+		this.passwordRetypeState = null;
+		this.recaptchaed = false;
 
-		window.on-recaptchaed = =>
-			this.recaptchaed = true
+		window.onEecaptchaed = () => {
+			this.recaptchaed = true;
 			this.update();
+		}
 
-		window.on-recaptcha-expired = =>
-			this.recaptchaed = false
+		window.onRecaptchaExpired = () => {
+			this.recaptchaed = false;
 			this.update();
+		}
 
 		this.on('mount', () => {
-			head = (document.get-elements-by-tag-name 'head).0' 
+			const head = (document.getElementsByTagName('head'))[0];
 			script = document.createElement 'script' 
-				..set-attribute 'src' \https://www.google.com/recaptcha/api.js
+				..setAttribute 'src' \https://www.google.com/recaptcha/api.js
 			head.appendChild script
+		});
 
 		on-change-username() {
 			username = this.refs.username.value
@@ -263,7 +266,7 @@
 				this.password-retype-state = 'not-match' 
 
 		onsubmit(e) {
-			e.prevent-default!
+			e.preventDefault();
 
 			username = this.refs.username.value
 			password = this.refs.password.value
@@ -286,7 +289,7 @@
 				grecaptcha.reset!
 				this.recaptchaed = false
 
-				locker.parent-node.remove-child locker
+				locker.parentNode.removeChild locker
 
 			false
 	</script>
diff --git a/src/web/app/common/tags/special-message.tag b/src/web/app/common/tags/special-message.tag
index 8304f87ec..41bd5fe32 100644
--- a/src/web/app/common/tags/special-message.tag
+++ b/src/web/app/common/tags/special-message.tag
@@ -20,8 +20,8 @@
 
 	</style>
 	<script>
-		now = new Date!
-		this.d = now.get-date!
-		this.m = now.get-month! + 1
+		const now = new Date();
+		this.d = now.getDate();
+		this.m = now.getMonth() + 1;
 	</script>
 </mk-special-message>
diff --git a/src/web/app/common/tags/url-preview.tag b/src/web/app/common/tags/url-preview.tag
index 74f952016..6daed4dbd 100644
--- a/src/web/app/common/tags/url-preview.tag
+++ b/src/web/app/common/tags/url-preview.tag
@@ -93,20 +93,22 @@
 	<script>
 		this.mixin('api');
 
-		this.url = this.opts.url
-		this.loading = true
+		this.url = this.opts.url;
+		this.loading = true;
 
 		this.on('mount', () => {
-			fetch CONFIG.url + '/api:url?url=' + @url
-			.then (res) =>
-				info <~ res.json!.then
-				this.title = info.title
-				this.description = info.description
-				this.thumbnail = info.thumbnail
-				this.icon = info.icon
-				this.sitename = info.sitename
+			fetch(CONFIG.url + '/api:url?url=' + this.url).then(res => {
+				res.json().then(info => {
+					this.title = info.title;
+					this.description = info.description;
+					this.thumbnail = info.thumbnail;
+					this.icon = info.icon;
+					this.sitename = info.sitename;
 
-				this.loading = false
-				this.update();
+					this.loading = false;
+					this.update();
+				});
+			});
+		});
 	</script>
 </mk-url-preview>
diff --git a/src/web/app/common/tags/url.tag b/src/web/app/common/tags/url.tag
index 596d2914c..0ad9e72b5 100644
--- a/src/web/app/common/tags/url.tag
+++ b/src/web/app/common/tags/url.tag
@@ -30,19 +30,20 @@
 
 	</style>
 	<script>
-		this.url = this.opts.href
+		this.url = this.opts.href;
 
 		this.on('before-mount', () => {
-			parser = document.createElement 'a' 
-			parser.href = @url
+			parser = document.createElement('a'); 
+			parser.href = this.url;
 
-			this.schema = parser.protocol
-			this.hostname = parser.hostname
-			this.port = parser.port
-			this.pathname = parser.pathname
-			this.query = parser.search
-			this.hash = parser.hash
+			this.schema = parser.protocol;
+			this.hostname = parser.hostname;
+			this.port = parser.port;
+			this.pathname = parser.pathname;
+			this.query = parser.search;
+			this.hash = parser.hash;
 
 			this.update();
+		});
 	</script>
 </mk-url>
diff --git a/src/web/app/desktop/tags/autocomplete-suggestion.tag b/src/web/app/desktop/tags/autocomplete-suggestion.tag
index 073352b19..cf735255b 100644
--- a/src/web/app/desktop/tags/autocomplete-suggestion.tag
+++ b/src/web/app/desktop/tags/autocomplete-suggestion.tag
@@ -124,25 +124,25 @@
 			switch (key)
 				| 10, 13 => // Key[ENTER]
 					if @select != -1
-						e.prevent-default!
-						e.stop-propagation!
+						e.preventDefault();
+						e.stopPropagation();
 						@complete @users[@select]
 					else
 						@close!
 				| 27 => // Key[ESC]
-					e.prevent-default!
-					e.stop-propagation!
+					e.preventDefault();
+					e.stopPropagation();
 					@close!
 				| 38 => // Key[↑]
 					if @select != -1
-						e.prevent-default!
-						e.stop-propagation!
+						e.preventDefault();
+						e.stopPropagation();
 						@select-prev!
 					else
 						@close!
 				| 9, 40 => // Key[TAB] or Key[↓]
-					e.prevent-default!
-					e.stop-propagation!
+					e.preventDefault();
+					e.stopPropagation();
 					@select-next!
 				| _ =>
 					@close!
@@ -167,7 +167,7 @@
 			this.refs.users.children.for-each (el) =>
 				el.remove-attribute 'data-selected' 
 
-			this.refs.users.children[@select].set-attribute 'data-selected' \true
+			this.refs.users.children[@select].setAttribute 'data-selected' \true
 			this.refs.users.children[@select].focus();
 
 		complete(user) {
@@ -177,11 +177,11 @@
 			this.opts.close!
 
 		function contains(parent, child)
-			node = child.parent-node
+			node = child.parentNode
 			while node?
 				if node == parent
 					return true
-				node = node.parent-node
+				node = node.parentNode
 			return false
 	</script>
 </mk-autocomplete-suggestion>
diff --git a/src/web/app/desktop/tags/contextmenu.tag b/src/web/app/desktop/tags/contextmenu.tag
index 114d48cf3..0d8cb313a 100644
--- a/src/web/app/desktop/tags/contextmenu.tag
+++ b/src/web/app/desktop/tags/contextmenu.tag
@@ -95,10 +95,10 @@
 	</style>
 	<script>
 		this.root.add-event-listener 'contextmenu' (e) =>
-			e.prevent-default!
+			e.preventDefault();
 
 		mousedown(e) {
-			e.prevent-default!
+			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 			return false
@@ -129,11 +129,11 @@
 			this.unmount();
 
 		function contains(parent, child)
-			node = child.parent-node
+			node = child.parentNode
 			while (node != null)
 				if (node == parent)
 					return true
-				node = node.parent-node
+				node = node.parentNode
 			return false
 	</script>
 </mk-contextmenu>
diff --git a/src/web/app/desktop/tags/donation.tag b/src/web/app/desktop/tags/donation.tag
index b01c0a44d..9ce2ed819 100644
--- a/src/web/app/desktop/tags/donation.tag
+++ b/src/web/app/desktop/tags/donation.tag
@@ -51,8 +51,8 @@
 		this.mixin('i');
 
 		close(e) {
-			e.prevent-default!
-			e.stop-propagation!
+			e.preventDefault();
+			e.stopPropagation();
 
 			this.I.data.no_donation = true
 			this.I.update!
diff --git a/src/web/app/desktop/tags/drive/base-contextmenu.tag b/src/web/app/desktop/tags/drive/base-contextmenu.tag
index 39e01558d..7eb5fd3b9 100644
--- a/src/web/app/desktop/tags/drive/base-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/base-contextmenu.tag
@@ -24,15 +24,15 @@
 			this.refs.ctx.open pos
 
 		create-folder() {
-			@browser.create-folder!
+			this.browser.create-folder!
 			this.refs.ctx.close!
 
 		upload() {
-			@browser.select-local-file!
+			this.browser.select-local-file!
 			this.refs.ctx.close!
 
 		url-upload() {
-			@browser.url-upload!
+			this.browser.url-upload!
 			this.refs.ctx.close!
 	</script>
 </mk-drive-browser-base-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index 02c886d14..2a93afbb2 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -293,7 +293,7 @@
 			@add-file file, true
 
 		on-stream-drive-file-updated(file) {
-			current = if @folder? then @folder.id else null
+			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				@remove-file file
 			else
@@ -303,7 +303,7 @@
 			@add-folder folder, true
 
 		on-stream-drive-folder-updated(folder) {
-			current = if @folder? then @folder.id else null
+			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
 				@remove-folder folder
 			else
@@ -350,29 +350,29 @@
 			document.document-element.add-event-listener 'mouseup' up
 
 		path-oncontextmenu(e) {
-			e.prevent-default!
+			e.preventDefault();
 			e.stop-immediate-propagation!
 			return false
 
 		ondragover(e) {
-			e.prevent-default!
-			e.stop-propagation!
+			e.preventDefault();
+			e.stopPropagation();
 
 			// ドラッグ元が自分自身の所有するアイテムかどうか
 			if !@is-drag-source
 				// ドラッグされてきたものがファイルだったら
-				if e.data-transfer.effect-allowed == 'all' 
-					e.data-transfer.drop-effect = 'copy' 
+				if e.dataTransfer.effect-allowed == 'all' 
+					e.dataTransfer.dropEffect = 'copy' 
 				else
-					e.data-transfer.drop-effect = 'move' 
+					e.dataTransfer.dropEffect = 'move' 
 				this.draghover = true
 			else
 				// 自分自身にはドロップさせない
-				e.data-transfer.drop-effect = 'none' 
+				e.dataTransfer.dropEffect = 'none' 
 			return false
 
 		ondragenter(e) {
-			e.prevent-default!
+			e.preventDefault();
 			if !@is-drag-source
 				this.draghover = true
 
@@ -380,19 +380,19 @@
 			this.draghover = false
 
 		ondrop(e) {
-			e.prevent-default!
-			e.stop-propagation!
+			e.preventDefault();
+			e.stopPropagation();
 
 			this.draghover = false
 
 			// ドロップされてきたものがファイルだったら
-			if e.data-transfer.files.length > 0
-				Array.prototype.for-each.call e.data-transfer.files, (file) =>
-					@upload file, @folder
+			if e.dataTransfer.files.length > 0
+				Array.prototype.for-each.call e.dataTransfer.files, (file) =>
+					@upload file, this.folder
 				return false
 
 			// データ取得
-			data = e.data-transfer.get-data 'text'
+			data = e.dataTransfer.get-data 'text'
 			if !data?
 				return false
 
@@ -402,12 +402,12 @@
 			// (ドライブの)ファイルだったら
 			if obj.type == 'file' 
 				file = obj.id
-				if (@files.some (f) => f.id == file)
+				if (this.files.some (f) => f.id == file)
 					return false
 				@remove-file file
 				this.api 'drive/files/update' do
 					file_id: file
-					folder_id: if @folder? then @folder.id else null
+					folder_id: if this.folder? then this.folder.id else null
 				.then =>
 					// something
 				.catch (err, text-status) =>
@@ -417,14 +417,14 @@
 			else if obj.type == 'folder' 
 				folder = obj.id
 				// 移動先が自分自身ならreject
-				if @folder? and folder == @folder.id
+				if this.folder? and folder == this.folder.id
 					return false
-				if (@folders.some (f) => f.id == folder)
+				if (this.folders.some (f) => f.id == folder)
 					return false
 				@remove-folder folder
 				this.api 'drive/folders/update' do
 					folder_id: folder
-					parent_id: if @folder? then @folder.id else null
+					parent_id: if this.folder? then this.folder.id else null
 				.then =>
 					// something
 				.catch (err) =>
@@ -439,7 +439,7 @@
 			return false
 
 		oncontextmenu(e) {
-			e.prevent-default!
+			e.preventDefault();
 			e.stop-immediate-propagation!
 
 			ctx = document.body.appendChild document.createElement 'mk-drive-browser-base-contextmenu' 
@@ -464,7 +464,7 @@
 			if url? and url != ''
 				this.api 'drive/files/upload_from_url' do
 					url: url
-					folder_id: if @folder? then @folder.id else undefined
+					folder_id: if this.folder? then this.folder.id else undefined
 
 				@dialog do
 					'<i class="fa fa-check"></i>アップロードをリクエストしました'
@@ -481,7 +481,7 @@
 
 			this.api 'drive/folders/create' do
 				name: name
-				folder_id: if @folder? then @folder.id else undefined
+				folder_id: if this.folder? then this.folder.id else undefined
 			.then (folder) =>
 				@add-folder folder, true
 				this.update();
@@ -492,7 +492,7 @@
 			files = this.refs.file-input.files
 			for i from 0 to files.length - 1
 				file = files.item i
-				@upload file, @folder
+				@upload file, this.folder
 
 		upload(file, folder) {
 			if folder? and typeof folder == 'object' 
@@ -500,7 +500,7 @@
 			this.refs.uploader.upload file, folder
 
 		get-selection() {
-			@files.filter (file) -> file._selected
+			this.files.filter (file) -> file._selected
 
 		new-window(folder-id) {
 			browser = document.body.appendChild document.createElement 'mk-drive-browser-window' 
@@ -538,55 +538,55 @@
 				console.error err
 
 		add-folder(folder, unshift = false) {
-			current = if @folder? then @folder.id else null
+			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
 				return
 
-			if (@folders.some (f) => f.id == folder.id)
-				exist = (@folders.map (f) -> f.id).index-of folder.id
-				@folders[exist] = folder
+			if (this.folders.some (f) => f.id == folder.id)
+				exist = (this.folders.map (f) -> f.id).index-of folder.id
+				this.folders[exist] = folder
 				this.update();
 				return
 
 			if unshift
-				@folders.unshift folder
+				this.folders.unshift folder
 			else
-				@folders.push folder
+				this.folders.push folder
 
 			this.update();
 
 		add-file(file, unshift = false) {
-			current = if @folder? then @folder.id else null
+			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				return
 
-			if (@files.some (f) => f.id == file.id)
-				exist = (@files.map (f) -> f.id).index-of file.id
-				@files[exist] = file
+			if (this.files.some (f) => f.id == file.id)
+				exist = (this.files.map (f) -> f.id).index-of file.id
+				this.files[exist] = file
 				this.update();
 				return
 
 			if unshift
-				@files.unshift file
+				this.files.unshift file
 			else
-				@files.push file
+				this.files.push file
 
 			this.update();
 
 		remove-folder(folder) {
 			if typeof folder == 'object' 
 				folder = folder.id
-			this.folders = @folders.filter (f) -> f.id != folder
+			this.folders = this.folders.filter (f) -> f.id != folder
 			this.update();
 
 		remove-file(file) {
 			if typeof file == 'object' 
 				file = file.id
-			this.files = @files.filter (f) -> f.id != file
+			this.files = this.files.filter (f) -> f.id != file
 			this.update();
 
 		go-root() {
-			if @folder != null
+			if this.folder != null
 				this.folder = null
 				this.hierarchy-folders = []
 				this.update();
@@ -608,7 +608,7 @@
 
 			// フォルダ一覧取得
 			this.api 'drive/folders' do
-				folder_id: if @folder? then @folder.id else null
+				folder_id: if this.folder? then this.folder.id else null
 				limit: folders-max + 1
 			.then (folders) =>
 				if folders.length == folders-max + 1
@@ -621,7 +621,7 @@
 
 			// ファイル一覧取得
 			this.api 'drive/files' do
-				folder_id: if @folder? then @folder.id else null
+				folder_id: if this.folder? then this.folder.id else null
 				limit: files-max + 1
 			.then (files) =>
 				if files.length == files-max + 1
@@ -645,11 +645,11 @@
 					flag := true
 
 		function contains(parent, child)
-			node = child.parent-node
+			node = child.parentNode
 			while node?
 				if node == parent
 					return true
-				node = node.parent-node
+				node = node.parentNode
 			return false
 	</script>
 </mk-drive-browser>
diff --git a/src/web/app/desktop/tags/drive/file-contextmenu.tag b/src/web/app/desktop/tags/drive/file-contextmenu.tag
index 5919599be..06e708562 100644
--- a/src/web/app/desktop/tags/drive/file-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/file-contextmenu.tag
@@ -63,10 +63,10 @@
 			name <~ @input-dialog do
 				'ファイル名の変更'
 				'新しいファイル名を入力してください'
-				@file.name
+				this.file.name
 
 			this.api 'drive/files/update' do
-				file_id: @file.id
+				file_id: this.file.id
 				name: name
 			.then =>
 				// something
@@ -81,15 +81,15 @@
 
 		set-avatar() {
 			this.refs.ctx.close!
-			@update-avatar this.I, null, @file
+			@update-avatar this.I, null, this.file
 
 		set-banner() {
 			this.refs.ctx.close!
-			@update-banner this.I, null, @file
+			@update-banner this.I, null, this.file
 
 		set-wallpaper() {
 			this.refs.ctx.close!
-			@update-wallpaper this.I, null, @file
+			@update-wallpaper this.I, null, this.file
 
 		add-app() {
 			@NotImplementedException!
diff --git a/src/web/app/desktop/tags/drive/file.tag b/src/web/app/desktop/tags/drive/file.tag
index e86948aee..d41c5279f 100644
--- a/src/web/app/desktop/tags/drive/file.tag
+++ b/src/web/app/desktop/tags/drive/file.tag
@@ -144,43 +144,43 @@
 
 	</style>
 	<script>
-		this.bytes-to-size = require('../../../common/scripts/bytes-to-size.js');
+		this.bytesToSize = require('../../../common/scripts/bytesToSize.js');
 
 		this.mixin('i');
 
 		this.file = this.opts.file
 		this.browser = this.parent
 
-		this.title = @file.name + '\n' + @file.type + ' ' + (@bytes-to-size @file.datasize)
+		this.title = this.file.name + '\n' + this.file.type + ' ' + (@bytesToSize this.file.datasize)
 
 		this.is-contextmenu-showing = false
 
 		onclick() {
-			if @browser.multiple
-				if @file._selected?
-					@file._selected = !@file._selected
+			if this.browser.multiple
+				if this.file._selected?
+					this.file._selected = !this.file._selected
 				else
-					@file._selected = true
-				@browser.trigger 'change-selection' @browser.get-selection!
+					this.file._selected = true
+				this.browser.trigger 'change-selection' this.browser.get-selection!
 			else
-				if @file._selected
-					@browser.trigger 'selected' @file
+				if this.file._selected
+					this.browser.trigger 'selected' this.file
 				else
-					@browser.files.for-each (file) =>
+					this.browser.files.for-each (file) =>
 						file._selected = false
-					@file._selected = true
-					@browser.trigger 'change-selection' @file
+					this.file._selected = true
+					this.browser.trigger 'change-selection' this.file
 
 		oncontextmenu(e) {
-			e.prevent-default!
+			e.preventDefault();
 			e.stop-immediate-propagation!
 
 			this.is-contextmenu-showing = true
 			this.update();
 			ctx = document.body.appendChild document.createElement 'mk-drive-browser-file-contextmenu' 
 			ctx = riot.mount ctx, do
-				browser: @browser
-				file: @file
+				browser: this.browser
+				file: this.file
 			ctx = ctx.0
 			ctx.open do
 				x: e.page-x - window.page-x-offset
@@ -191,19 +191,19 @@
 			return false
 
 		ondragstart(e) {
-			e.data-transfer.effect-allowed = 'move' 
-			e.data-transfer.set-data 'text' JSON.stringify do
+			e.dataTransfer.effect-allowed = 'move' 
+			e.dataTransfer.set-data 'text' JSON.stringify do
 				type: 'file' 
-				id: @file.id
-				file: @file
+				id: this.file.id
+				file: this.file
 			this.is-dragging = true
 
 			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
 			// (=あなたの子供が、ドラッグを開始しましたよ)
-			@browser.is-drag-source = true
+			this.browser.is-drag-source = true
 
 		ondragend(e) {
 			this.is-dragging = false
-			@browser.is-drag-source = false
+			this.browser.is-drag-source = false
 	</script>
 </mk-drive-browser-file>
diff --git a/src/web/app/desktop/tags/drive/folder-contextmenu.tag b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
index 20cb264e5..df094d0bc 100644
--- a/src/web/app/desktop/tags/drive/folder-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
@@ -32,19 +32,19 @@
 				this.unmount();
 
 		move() {
-			@browser.move @folder.id
+			this.browser.move this.folder.id
 			this.refs.ctx.close!
 
 		new-window() {
-			@browser.new-window @folder.id
+			this.browser.new-window this.folder.id
 			this.refs.ctx.close!
 
 		create-folder() {
-			@browser.create-folder!
+			this.browser.create-folder!
 			this.refs.ctx.close!
 
 		upload() {
-			@browser.select-lcoal-file!
+			this.browser.select-lcoal-file!
 			this.refs.ctx.close!
 
 		rename() {
@@ -53,10 +53,10 @@
 			name <~ @input-dialog do
 				'フォルダ名の変更'
 				'新しいフォルダ名を入力してください'
-				@folder.name
+				this.folder.name
 
 			this.api 'drive/folders/update' do
-				folder_id: @folder.id
+				folder_id: this.folder.id
 				name: name
 			.then =>
 				// something
diff --git a/src/web/app/desktop/tags/drive/folder.tag b/src/web/app/desktop/tags/drive/folder.tag
index e14f70f41..2d58ddefc 100644
--- a/src/web/app/desktop/tags/drive/folder.tag
+++ b/src/web/app/desktop/tags/drive/folder.tag
@@ -56,13 +56,13 @@
 		this.folder = this.opts.folder
 		this.browser = this.parent
 
-		this.title = @folder.name
+		this.title = this.folder.name
 		this.hover = false
 		this.draghover = false
 		this.is-contextmenu-showing = false
 
 		onclick() {
-			@browser.move @folder
+			this.browser.move this.folder
 
 		onmouseover() {
 			this.hover = true
@@ -71,19 +71,19 @@
 			this.hover = false
 
 		ondragover(e) {
-			e.prevent-default!
-			e.stop-propagation!
+			e.preventDefault();
+			e.stopPropagation();
 
 			// 自分自身がドラッグされていない場合
 			if !@is-dragging
 				// ドラッグされてきたものがファイルだったら
-				if e.data-transfer.effect-allowed == 'all' 
-					e.data-transfer.drop-effect = 'copy' 
+				if e.dataTransfer.effect-allowed == 'all' 
+					e.dataTransfer.dropEffect = 'copy' 
 				else
-					e.data-transfer.drop-effect = 'move' 
+					e.dataTransfer.dropEffect = 'move' 
 			else
 				// 自分自身にはドロップさせない
-				e.data-transfer.drop-effect = 'none' 
+				e.dataTransfer.dropEffect = 'none' 
 			return false
 
 		ondragenter() {
@@ -94,17 +94,17 @@
 			this.draghover = false
 
 		ondrop(e) {
-			e.stop-propagation!
+			e.stopPropagation();
 			this.draghover = false
 
 			// ファイルだったら
-			if e.data-transfer.files.length > 0
-				Array.prototype.for-each.call e.data-transfer.files, (file) =>
-					@browser.upload file, @folder
+			if e.dataTransfer.files.length > 0
+				Array.prototype.for-each.call e.dataTransfer.files, (file) =>
+					this.browser.upload file, this.folder
 				return false
 
 			// データ取得
-			data = e.data-transfer.get-data 'text'
+			data = e.dataTransfer.get-data 'text'
 			if !data?
 				return false
 
@@ -114,10 +114,10 @@
 			// (ドライブの)ファイルだったら
 			if obj.type == 'file' 
 				file = obj.id
-				@browser.remove-file file
+				this.browser.remove-file file
 				this.api 'drive/files/update' do
 					file_id: file
-					folder_id: @folder.id
+					folder_id: this.folder.id
 				.then =>
 					// something
 				.catch (err, text-status) =>
@@ -127,12 +127,12 @@
 			else if obj.type == 'folder' 
 				folder = obj.id
 				// 移動先が自分自身ならreject
-				if folder == @folder.id
+				if folder == this.folder.id
 					return false
-				@browser.remove-folder folder
+				this.browser.remove-folder folder
 				this.api 'drive/folders/update' do
 					folder_id: folder
-					parent_id: @folder.id
+					parent_id: this.folder.id
 				.then =>
 					// something
 				.catch (err) =>
@@ -147,30 +147,30 @@
 			return false
 
 		ondragstart(e) {
-			e.data-transfer.effect-allowed = 'move' 
-			e.data-transfer.set-data 'text' JSON.stringify do
+			e.dataTransfer.effect-allowed = 'move' 
+			e.dataTransfer.set-data 'text' JSON.stringify do
 				type: 'folder' 
-				id: @folder.id
+				id: this.folder.id
 			this.is-dragging = true
 
 			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
 			// (=あなたの子供が、ドラッグを開始しましたよ)
-			@browser.is-drag-source = true
+			this.browser.is-drag-source = true
 
 		ondragend(e) {
 			this.is-dragging = false
-			@browser.is-drag-source = false
+			this.browser.is-drag-source = false
 
 		oncontextmenu(e) {
-			e.prevent-default!
+			e.preventDefault();
 			e.stop-immediate-propagation!
 
 			this.is-contextmenu-showing = true
 			this.update();
 			ctx = document.body.appendChild document.createElement 'mk-drive-browser-folder-contextmenu' 
 			ctx = riot.mount ctx, do
-				browser: @browser
-				folder: @folder
+				browser: this.browser
+				folder: this.folder
 			ctx = ctx.0
 			ctx.open do
 				x: e.page-x - window.page-x-offset
diff --git a/src/web/app/desktop/tags/drive/nav-folder.tag b/src/web/app/desktop/tags/drive/nav-folder.tag
index afa628775..8f8f00783 100644
--- a/src/web/app/desktop/tags/drive/nav-folder.tag
+++ b/src/web/app/desktop/tags/drive/nav-folder.tag
@@ -17,7 +17,7 @@
 		this.hover = false
 
 		onclick() {
-			@browser.move @folder
+			this.browser.move this.folder
 
 		onmouseover() {
 			this.hover = true
@@ -26,39 +26,39 @@
 			this.hover = false
 
 		ondragover(e) {
-			e.prevent-default!
-			e.stop-propagation!
+			e.preventDefault();
+			e.stopPropagation();
 
 			// このフォルダがルートかつカレントディレクトリならドロップ禁止
-			if @folder == null and @browser.folder == null
-				e.data-transfer.drop-effect = 'none' 
+			if this.folder == null and this.browser.folder == null
+				e.dataTransfer.dropEffect = 'none' 
 			// ドラッグされてきたものがファイルだったら
-			else if e.data-transfer.effect-allowed == 'all' 
-				e.data-transfer.drop-effect = 'copy' 
+			else if e.dataTransfer.effect-allowed == 'all' 
+				e.dataTransfer.dropEffect = 'copy' 
 			else
-				e.data-transfer.drop-effect = 'move' 
+				e.dataTransfer.dropEffect = 'move' 
 			return false
 
 		ondragenter() {
-			if @folder != null or @browser.folder != null
+			if this.folder != null or this.browser.folder != null
 				this.draghover = true
 
 		ondragleave() {
-			if @folder != null or @browser.folder != null
+			if this.folder != null or this.browser.folder != null
 				this.draghover = false
 
 		ondrop(e) {
-			e.stop-propagation!
+			e.stopPropagation();
 			this.draghover = false
 
 			// ファイルだったら
-			if e.data-transfer.files.length > 0
-				Array.prototype.for-each.call e.data-transfer.files, (file) =>
-					@browser.upload file, @folder
+			if e.dataTransfer.files.length > 0
+				Array.prototype.for-each.call e.dataTransfer.files, (file) =>
+					this.browser.upload file, this.folder
 				return false
 
 			// データ取得
-			data = e.data-transfer.get-data 'text'
+			data = e.dataTransfer.get-data 'text'
 			if !data?
 				return false
 
@@ -68,10 +68,10 @@
 			// (ドライブの)ファイルだったら
 			if obj.type == 'file' 
 				file = obj.id
-				@browser.remove-file file
+				this.browser.remove-file file
 				this.api 'drive/files/update' do
 					file_id: file
-					folder_id: if @folder? then @folder.id else null
+					folder_id: if this.folder? then this.folder.id else null
 				.then =>
 					// something
 				.catch (err, text-status) =>
@@ -81,12 +81,12 @@
 			else if obj.type == 'folder' 
 				folder = obj.id
 				// 移動先が自分自身ならreject
-				if @folder? and folder == @folder.id
+				if this.folder? and folder == this.folder.id
 					return false
-				@browser.remove-folder folder
+				this.browser.remove-folder folder
 				this.api 'drive/folders/update' do
 					folder_id: folder
-					parent_id: if @folder? then @folder.id else null
+					parent_id: if this.folder? then this.folder.id else null
 				.then =>
 					// something
 				.catch (err, text-status) =>
diff --git a/src/web/app/desktop/tags/input-dialog.tag b/src/web/app/desktop/tags/input-dialog.tag
index a7dfdb807..c2cf09330 100644
--- a/src/web/app/desktop/tags/input-dialog.tag
+++ b/src/web/app/desktop/tags/input-dialog.tag
@@ -150,8 +150,8 @@
 
 		on-keydown(e) {
 			if e.which == 13 // Enter
-				e.prevent-default!
-				e.stop-propagation!
+				e.preventDefault();
+				e.stopPropagation();
 				@ok!
 	</script>
 </mk-input-dialog>
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index 760a585ce..b1c06143b 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -345,13 +345,13 @@
 			this.update();
 
 		ondragover(e) {
-			e.stop-propagation!
+			e.stopPropagation();
 			this.draghover = true
 			// ドラッグされてきたものがファイルだったら
-			if e.data-transfer.effect-allowed == 'all' 
-				e.data-transfer.drop-effect = 'copy' 
+			if e.dataTransfer.effect-allowed == 'all' 
+				e.dataTransfer.dropEffect = 'copy' 
 			else
-				e.data-transfer.drop-effect = 'move' 
+				e.dataTransfer.dropEffect = 'move' 
 			return false
 
 		ondragenter(e) {
@@ -361,18 +361,18 @@
 			this.draghover = false
 
 		ondrop(e) {
-			e.prevent-default!
-			e.stop-propagation!
+			e.preventDefault();
+			e.stopPropagation();
 			this.draghover = false
 
 			// ファイルだったら
-			if e.data-transfer.files.length > 0
-				Array.prototype.for-each.call e.data-transfer.files, (file) =>
+			if e.dataTransfer.files.length > 0
+				Array.prototype.for-each.call e.dataTransfer.files, (file) =>
 					@upload file
 				return false
 
 			// データ取得
-			data = e.data-transfer.get-data 'text'
+			data = e.dataTransfer.get-data 'text'
 			if !data?
 				return false
 
@@ -422,12 +422,12 @@
 
 		add-file(file) {
 			file._remove = =>
-				this.files = @files.filter (x) -> x.id != file.id
-				this.trigger 'change-files' @files
+				this.files = this.files.filter (x) -> x.id != file.id
+				this.trigger 'change-files' this.files
 				this.update();
 
-			@files.push file
-			this.trigger 'change-files' @files
+			this.files.push file
+			this.trigger 'change-files' this.files
 			this.update();
 
 		add-poll() {
@@ -440,8 +440,8 @@
 		post(e) {
 			this.wait = true
 
-			files = if @files? and @files.length > 0
-				then @files.map (f) -> f.id
+			files = if this.files? and this.files.length > 0
+				then this.files.map (f) -> f.id
 				else undefined
 
 			this.api 'posts/create' do
diff --git a/src/web/app/desktop/tags/select-file-from-drive-window.tag b/src/web/app/desktop/tags/select-file-from-drive-window.tag
index f4cfd5503..c8fc02d22 100644
--- a/src/web/app/desktop/tags/select-file-from-drive-window.tag
+++ b/src/web/app/desktop/tags/select-file-from-drive-window.tag
@@ -155,7 +155,7 @@
 			this.refs.window.refs.browser.select-local-file!
 
 		ok() {
-			this.trigger 'selected' @file
+			this.trigger 'selected' this.file
 			this.refs.window.close!
 	</script>
 </mk-select-file-from-drive-window>
diff --git a/src/web/app/desktop/tags/set-avatar-suggestion.tag b/src/web/app/desktop/tags/set-avatar-suggestion.tag
index 149144edf..e398a6ed2 100644
--- a/src/web/app/desktop/tags/set-avatar-suggestion.tag
+++ b/src/web/app/desktop/tags/set-avatar-suggestion.tag
@@ -38,8 +38,8 @@
 			@update-avatar this.I
 
 		close(e) {
-			e.prevent-default!
-			e.stop-propagation!
+			e.preventDefault();
+			e.stopPropagation();
 			this.unmount();
 	</script>
 </mk-set-avatar-suggestion>
diff --git a/src/web/app/desktop/tags/set-banner-suggestion.tag b/src/web/app/desktop/tags/set-banner-suggestion.tag
index a1e9eb4ed..73c67a02b 100644
--- a/src/web/app/desktop/tags/set-banner-suggestion.tag
+++ b/src/web/app/desktop/tags/set-banner-suggestion.tag
@@ -38,8 +38,8 @@
 			@update-banner this.I
 
 		close(e) {
-			e.prevent-default!
-			e.stop-propagation!
+			e.preventDefault();
+			e.stopPropagation();
 			this.unmount();
 	</script>
 </mk-set-banner-suggestion>
diff --git a/src/web/app/desktop/tags/timeline-post.tag b/src/web/app/desktop/tags/timeline-post.tag
index 8ccf2b57c..ea1bed257 100644
--- a/src/web/app/desktop/tags/timeline-post.tag
+++ b/src/web/app/desktop/tags/timeline-post.tag
@@ -394,7 +394,7 @@
 				should-be-cancel = false
 
 			if should-be-cancel
-				e.prevent-default!
+				e.preventDefault();
 
 		function focus(el, fn)
 			target = fn el
diff --git a/src/web/app/desktop/tags/ui-header-account.tag b/src/web/app/desktop/tags/ui-header-account.tag
index a5308b014..fa3f60a61 100644
--- a/src/web/app/desktop/tags/ui-header-account.tag
+++ b/src/web/app/desktop/tags/ui-header-account.tag
@@ -188,7 +188,7 @@
 				el.remove-event-listener 'mousedown' @mousedown
 
 		mousedown(e) {
-			e.prevent-default!
+			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 			return false
@@ -202,11 +202,11 @@
 			riot.mount document.body.appendChild document.createElement 'mk-settings-window' 
 
 		function contains(parent, child)
-			node = child.parent-node
+			node = child.parentNode
 			while node?
 				if node == parent
 					return true
-				node = node.parent-node
+				node = node.parentNode
 			return false
 	</script>
 </mk-ui-header-account>
diff --git a/src/web/app/desktop/tags/ui-header-notifications.tag b/src/web/app/desktop/tags/ui-header-notifications.tag
index d166df36e..1768f915e 100644
--- a/src/web/app/desktop/tags/ui-header-notifications.tag
+++ b/src/web/app/desktop/tags/ui-header-notifications.tag
@@ -98,17 +98,17 @@
 				el.remove-event-listener 'mousedown' @mousedown
 
 		mousedown(e) {
-			e.prevent-default!
+			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 			return false
 
 		function contains(parent, child)
-			node = child.parent-node
+			node = child.parentNode
 			while node?
 				if node == parent
 					return true
-				node = node.parent-node
+				node = node.parentNode
 			return false
 	</script>
 </mk-ui-header-notifications>
diff --git a/src/web/app/desktop/tags/ui-header-search.tag b/src/web/app/desktop/tags/ui-header-search.tag
index 702c70efc..69d2dd732 100644
--- a/src/web/app/desktop/tags/ui-header-search.tag
+++ b/src/web/app/desktop/tags/ui-header-search.tag
@@ -35,7 +35,7 @@
 		this.mixin('page');
 
 		onsubmit(e) {
-			e.prevent-default!
+			e.preventDefault();
 			@page '/search:' + this.refs.q.value
 	</script>
 </mk-ui-header-search>
diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag
index 78bf6117c..1ecb0f570 100644
--- a/src/web/app/desktop/tags/ui.tag
+++ b/src/web/app/desktop/tags/ui.tag
@@ -31,7 +31,7 @@
 			tag = e.target.tag-name.to-lower-case!
 			if tag != 'input' and tag != 'textarea' 
 				if e.which == 80 or e.which == 78 // p or n
-					e.prevent-default!
+					e.preventDefault();
 					@open-post-form!
 	</script>
 </mk-ui>
diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index f3d8ff7be..71084f8b5 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -208,7 +208,7 @@
 			this.refs.main.style.left = (window.inner-width / 2) - (this.refs.main.offset-width / 2) + 'px' 
 
 			this.refs.header.add-event-listener 'contextmenu' (e) =>
-				e.prevent-default!
+				e.preventDefault();
 
 			window.add-event-listener 'resize' this.on-browser-resize
 
@@ -315,7 +315,7 @@
 				if @is-modal then this.refs.bg.style.z-index = z + 1
 
 		repel-move(e) {
-			e.stop-propagation!
+			e.stopPropagation();
 			return true
 
 		bg-click() {
@@ -328,7 +328,7 @@
 
 		// ヘッダー掴み時
 		on-header-mousedown(e) {
-			e.prevent-default!
+			e.preventDefault();
 
 			if not contains this.refs.main, document.active-element
 				this.refs.main.focus();
@@ -370,7 +370,7 @@
 
 		// 上ハンドル掴み時
 		on-top-handle-mousedown(e) {
-			e.prevent-default!
+			e.preventDefault();
 
 			base = e.client-y
 			height = parse-int((get-computed-style this.refs.main, '').height, 10)
@@ -392,7 +392,7 @@
 
 		// 右ハンドル掴み時
 		on-right-handle-mousedown(e) {
-			e.prevent-default!
+			e.preventDefault();
 
 			base = e.client-x
 			width = parse-int((get-computed-style this.refs.main, '').width, 10)
@@ -412,7 +412,7 @@
 
 		// 下ハンドル掴み時
 		on-bottom-handle-mousedown(e) {
-			e.prevent-default!
+			e.preventDefault();
 
 			base = e.client-y
 			height = parse-int((get-computed-style this.refs.main, '').height, 10)
@@ -432,7 +432,7 @@
 
 		// 左ハンドル掴み時
 		on-left-handle-mousedown(e) {
-			e.prevent-default!
+			e.preventDefault();
 
 			base = e.client-x
 			width = parse-int((get-computed-style this.refs.main, '').width, 10)
@@ -499,21 +499,21 @@
 			window.remove-event-listener 'mouseup'    drag-clear
 
 		ondragover(e) {
-			e.data-transfer.drop-effect = 'none' 
+			e.dataTransfer.dropEffect = 'none' 
 
 		on-keydown(e) {
 			if e.which == 27 // Esc
 				if @can-close
-					e.prevent-default!
-					e.stop-propagation!
+					e.preventDefault();
+					e.stopPropagation();
 					@close!
 
 		function contains(parent, child)
-			node = child.parent-node
+			node = child.parentNode
 			while node?
 				if node == parent
 					return true
-				node = node.parent-node
+				node = node.parentNode
 			return false
 	</script>
 </mk-window>
diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag
index a298d5ce0..84e099612 100644
--- a/src/web/app/dev/tags/new-app-form.tag
+++ b/src/web/app/dev/tags/new-app-form.tag
@@ -238,6 +238,6 @@
 			.catch =>
 				alert 'アプリの作成に失敗しました。再度お試しください。'
 
-				locker.parent-node.remove-child locker
+				locker.parentNode.removeChild locker
 	</script>
 </mk-new-app-form>
diff --git a/src/web/app/mobile/tags/drive-selector.tag b/src/web/app/mobile/tags/drive-selector.tag
index d1ecc29b5..ce9bdd2b5 100644
--- a/src/web/app/mobile/tags/drive-selector.tag
+++ b/src/web/app/mobile/tags/drive-selector.tag
@@ -68,7 +68,7 @@
 			this.unmount();
 
 		ok() {
-			this.trigger 'selected' @files
+			this.trigger 'selected' this.files
 			this.unmount();
 	</script>
 </mk-drive-selector>
diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag
index f7fc07f00..ddaf60061 100644
--- a/src/web/app/mobile/tags/drive.tag
+++ b/src/web/app/mobile/tags/drive.tag
@@ -171,7 +171,7 @@
 			@add-file file, true
 
 		on-stream-drive-file-updated(file) {
-			current = if @folder? then @folder.id else null
+			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				@remove-file file
 			else
@@ -181,7 +181,7 @@
 			@add-folder folder, true
 
 		on-stream-drive-folder-updated(folder) {
-			current = if @folder? then @folder.id else null
+			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
 				@remove-folder folder
 			else
@@ -221,58 +221,58 @@
 					x folder.parent
 
 				this.update();
-				this.trigger 'open-folder' @folder, silent
+				this.trigger 'open-folder' this.folder, silent
 				@load!
 			.catch (err, text-status) ->
 				console.error err
 
 		add-folder(folder, unshift = false) {
-			current = if @folder? then @folder.id else null
+			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
 				return
 
-			if (@folders.some (f) => f.id == folder.id)
+			if (this.folders.some (f) => f.id == folder.id)
 				return
 
 			if unshift
-				@folders.unshift folder
+				this.folders.unshift folder
 			else
-				@folders.push folder
+				this.folders.push folder
 
 			this.update();
 
 		add-file(file, unshift = false) {
-			current = if @folder? then @folder.id else null
+			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				return
 
-			if (@files.some (f) => f.id == file.id)
-				exist = (@files.map (f) -> f.id).index-of file.id
-				@files[exist] = file
+			if (this.files.some (f) => f.id == file.id)
+				exist = (this.files.map (f) -> f.id).index-of file.id
+				this.files[exist] = file
 				this.update();
 				return
 
 			if unshift
-				@files.unshift file
+				this.files.unshift file
 			else
-				@files.push file
+				this.files.push file
 
 			this.update();
 
 		remove-folder(folder) {
 			if typeof folder == 'object' 
 				folder = folder.id
-			this.folders = @folders.filter (f) -> f.id != folder
+			this.folders = this.folders.filter (f) -> f.id != folder
 			this.update();
 
 		remove-file(file) {
 			if typeof file == 'object' 
 				file = file.id
-			this.files = @files.filter (f) -> f.id != file
+			this.files = this.files.filter (f) -> f.id != file
 			this.update();
 
 		go-root() {
-			if @folder != null or @file != null
+			if this.folder != null or this.file != null
 				this.file = null
 				this.folder = null
 				this.hierarchy-folders = []
@@ -298,7 +298,7 @@
 
 			// フォルダ一覧取得
 			this.api 'drive/folders' do
-				folder_id: if @folder? then @folder.id else null
+				folder_id: if this.folder? then this.folder.id else null
 				limit: folders-max + 1
 			.then (folders) =>
 				if folders.length == folders-max + 1
@@ -311,7 +311,7 @@
 
 			// ファイル一覧取得
 			this.api 'drive/files' do
-				folder_id: if @folder? then @folder.id else null
+				folder_id: if this.folder? then this.folder.id else null
 				limit: files-max + 1
 			.then (files) =>
 				if files.length == files-max + 1
@@ -372,6 +372,6 @@
 					x file.folder
 
 				this.update();
-				this.trigger 'open-file' @file, silent
+				this.trigger 'open-file' this.file, silent
 	</script>
 </mk-drive>
diff --git a/src/web/app/mobile/tags/drive/file-viewer.tag b/src/web/app/mobile/tags/drive/file-viewer.tag
index 86f6ca0c5..eff41ab85 100644
--- a/src/web/app/mobile/tags/drive/file-viewer.tag
+++ b/src/web/app/mobile/tags/drive/file-viewer.tag
@@ -180,22 +180,22 @@
 
 	</style>
 	<script>
-		this.bytes-to-size = require('../../../common/scripts/bytes-to-size.js');
-		this.get-gcd = require('../../../common/scripts/gcd.js');
+		this.bytesToSize = require('../../../common/scripts/bytes-to-size.js');
+		this.getGcd = require('../../../common/scripts/gcd.js');
 
 		this.mixin('api');
 
 		this.file = this.opts.file
-		this.kind = @file.type.split '/' .0
+		this.kind = this.file.type.split '/' .0
 
 		rename() {
-			name = window.prompt '名前を変更' @file.name
-			if name? and name != '' and name != @file.name
+			name = window.prompt '名前を変更' this.file.name
+			if name? and name != '' and name != this.file.name
 				this.api 'drive/files/update' do
-					file_id: @file.id
+					file_id: this.file.id
 					name: name
 				.then =>
-					this.parent.cf @file, true
+					this.parent.cf this.file, true
 
 	</script>
 </mk-drive-file-viewer>
diff --git a/src/web/app/mobile/tags/drive/file.tag b/src/web/app/mobile/tags/drive/file.tag
index 16fa74b4b..c83134919 100644
--- a/src/web/app/mobile/tags/drive/file.tag
+++ b/src/web/app/mobile/tags/drive/file.tag
@@ -122,16 +122,16 @@
 
 	</style>
 	<script>
-		this.bytes-to-size = require('../../../common/scripts/bytes-to-size.js');
+		this.bytesToSize = require('../../../common/scripts/bytesToSize.js');
 
 		this.browser = this.parent
 		this.file = this.opts.file
-		this.is-selected = @browser.selected-files.some (f) => f.id == @file.id
+		this.is-selected = this.browser.selected-files.some (f) => f.id == this.file.id
 
-		@browser.on('change-selected', (selects) => {
-			this.is-selected = selects.some (f) => f.id == @file.id
+		this.browser.on('change-selected', (selects) => {
+			this.is-selected = selects.some (f) => f.id == this.file.id
 
 		onclick() {
-			@browser.choose-file @file
+			this.browser.choose-file this.file
 	</script>
 </mk-drive-file>
diff --git a/src/web/app/mobile/tags/drive/folder.tag b/src/web/app/mobile/tags/drive/folder.tag
index aeb1601a6..c536fed9d 100644
--- a/src/web/app/mobile/tags/drive/folder.tag
+++ b/src/web/app/mobile/tags/drive/folder.tag
@@ -41,6 +41,6 @@
 		this.folder = this.opts.folder
 
 		onclick() {
-			@browser.move @folder
+			this.browser.move this.folder
 	</script>
 </mk-drive-folder>
diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag
index e53339dd4..72778f3b4 100644
--- a/src/web/app/mobile/tags/post-form.tag
+++ b/src/web/app/mobile/tags/post-form.tag
@@ -238,12 +238,12 @@
 
 		add-file(file) {
 			file._remove = =>
-				this.files = @files.filter (x) -> x.id != file.id
-				this.trigger 'change-files' @files
+				this.files = this.files.filter (x) -> x.id != file.id
+				this.trigger 'change-files' this.files
 				this.update();
 
-			@files.push file
-			this.trigger 'change-files' @files
+			this.files.push file
+			this.trigger 'change-files' this.files
 			this.update();
 
 		add-poll() {
@@ -256,8 +256,8 @@
 		post() {
 			this.wait = true
 
-			files = if @files? and @files.length > 0
-				then @files.map (f) -> f.id
+			files = if this.files? and this.files.length > 0
+				then this.files.map (f) -> f.id
 				else undefined
 
 			this.api 'posts/create' do

From 91d8ee5a52ece1cb78e5e3bb74178d41761d540f Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 10:34:57 +0900
Subject: [PATCH 04/32] wip

---
 src/web/app/auth/tags/form.tag                |  4 +-
 src/web/app/auth/tags/index.tag               |  2 +-
 src/web/app/common/tags/core-error.tag        |  2 +-
 src/web/app/common/tags/messaging/form.tag    | 12 ++--
 src/web/app/common/tags/messaging/index.tag   |  6 +-
 src/web/app/common/tags/messaging/room.tag    | 30 ++++-----
 src/web/app/common/tags/poll-editor.tag       | 10 +--
 src/web/app/common/tags/poll.tag              |  4 +-
 src/web/app/common/tags/signin-history.tag    |  2 +-
 src/web/app/common/tags/signin.tag            |  4 +-
 src/web/app/common/tags/signup.tag            |  8 +--
 src/web/app/common/tags/time.tag              |  2 +-
 src/web/app/common/tags/uploader.tag          |  2 +-
 src/web/app/desktop/tags/analog-clock.tag     |  2 +-
 .../desktop/tags/autocomplete-suggestion.tag  | 24 +++----
 .../app/desktop/tags/big-follow-button.tag    |  6 +-
 src/web/app/desktop/tags/contextmenu.tag      | 12 ++--
 src/web/app/desktop/tags/crop-window.tag      |  6 +-
 src/web/app/desktop/tags/dialog.tag           |  4 +-
 src/web/app/desktop/tags/donation.tag         |  2 +-
 .../desktop/tags/drive/base-contextmenu.tag   |  8 +--
 .../app/desktop/tags/drive/browser-window.tag |  2 +-
 src/web/app/desktop/tags/drive/browser.tag    | 58 ++++++++---------
 .../desktop/tags/drive/file-contextmenu.tag   | 16 ++---
 src/web/app/desktop/tags/drive/file.tag       |  8 +--
 .../desktop/tags/drive/folder-contextmenu.tag | 12 ++--
 src/web/app/desktop/tags/drive/folder.tag     | 20 +++---
 src/web/app/desktop/tags/drive/nav-folder.tag | 14 ++---
 src/web/app/desktop/tags/follow-button.tag    |  6 +-
 .../app/desktop/tags/following-setuper.tag    |  6 +-
 src/web/app/desktop/tags/go-top.tag           |  8 +--
 .../desktop/tags/home-widgets/calendar.tag    |  2 +-
 .../desktop/tags/home-widgets/mentions.tag    | 18 +++---
 .../tags/home-widgets/notifications.tag       |  2 +-
 .../tags/home-widgets/photo-stream.tag        |  2 +-
 .../app/desktop/tags/home-widgets/profile.tag |  4 +-
 .../desktop/tags/home-widgets/rss-reader.tag  |  4 +-
 .../desktop/tags/home-widgets/timeline.tag    | 22 +++----
 .../app/desktop/tags/home-widgets/tips.tag    |  4 +-
 .../tags/home-widgets/user-recommendation.tag |  4 +-
 src/web/app/desktop/tags/image-dialog.tag     |  2 +-
 src/web/app/desktop/tags/images-viewer.tag    |  4 +-
 src/web/app/desktop/tags/input-dialog.tag     |  6 +-
 src/web/app/desktop/tags/notifications.tag    |  2 +-
 src/web/app/desktop/tags/pages/entrance.tag   |  6 +-
 .../desktop/tags/pages/entrance/signin.tag    |  2 +-
 src/web/app/desktop/tags/pages/home.tag       |  8 +--
 src/web/app/desktop/tags/post-detail-sub.tag  |  2 +-
 src/web/app/desktop/tags/post-detail.tag      |  8 +--
 src/web/app/desktop/tags/post-form.tag        | 34 +++++-----
 src/web/app/desktop/tags/progress-dialog.tag  |  4 +-
 .../app/desktop/tags/repost-form-window.tag   |  6 +-
 src/web/app/desktop/tags/repost-form.tag      |  6 +-
 src/web/app/desktop/tags/search-posts.tag     | 14 ++---
 .../tags/select-file-from-drive-window.tag    |  6 +-
 .../desktop/tags/set-avatar-suggestion.tag    |  4 +-
 .../desktop/tags/set-banner-suggestion.tag    |  4 +-
 src/web/app/desktop/tags/settings-window.tag  |  2 +-
 src/web/app/desktop/tags/settings.tag         | 12 ++--
 src/web/app/desktop/tags/timeline-post.tag    | 10 +--
 src/web/app/desktop/tags/timeline.tag         | 12 ++--
 .../app/desktop/tags/ui-header-account.tag    | 16 ++---
 src/web/app/desktop/tags/ui-header-clock.tag  |  2 +-
 src/web/app/desktop/tags/ui-header-nav.tag    |  6 +-
 .../desktop/tags/ui-header-notifications.tag  | 12 ++--
 .../desktop/tags/ui-header-post-button.tag    |  2 +-
 src/web/app/desktop/tags/ui-header-search.tag |  2 +-
 src/web/app/desktop/tags/ui.tag               | 10 +--
 src/web/app/desktop/tags/user-followers.tag   |  2 +-
 src/web/app/desktop/tags/user-following.tag   |  2 +-
 src/web/app/desktop/tags/user-header.tag      | 16 ++---
 src/web/app/desktop/tags/user-preview.tag     |  2 +-
 src/web/app/desktop/tags/user-profile.tag     |  4 +-
 src/web/app/desktop/tags/user-timeline.tag    | 26 ++++----
 src/web/app/desktop/tags/users-list.tag       |  6 +-
 src/web/app/desktop/tags/window.tag           | 62 +++++++++----------
 src/web/app/dev/tags/new-app-form.tag         |  4 +-
 src/web/app/mobile/tags/drive-selector.tag    |  4 +-
 src/web/app/mobile/tags/drive.tag             | 30 ++++-----
 src/web/app/mobile/tags/drive/file-viewer.tag |  2 +-
 src/web/app/mobile/tags/drive/file.tag        |  2 +-
 src/web/app/mobile/tags/drive/folder.tag      |  2 +-
 src/web/app/mobile/tags/follow-button.tag     |  6 +-
 src/web/app/mobile/tags/home-timeline.tag     |  8 +--
 src/web/app/mobile/tags/images-viewer.tag     |  2 +-
 src/web/app/mobile/tags/notifications.tag     |  2 +-
 src/web/app/mobile/tags/page/entrance.tag     |  6 +-
 src/web/app/mobile/tags/page/home.tag         |  8 +--
 src/web/app/mobile/tags/post-detail.tag       |  8 +--
 src/web/app/mobile/tags/post-form.tag         | 24 +++----
 src/web/app/mobile/tags/search-posts.tag      |  2 +-
 src/web/app/mobile/tags/timeline-post.tag     |  6 +-
 src/web/app/mobile/tags/timeline.tag          | 10 +--
 src/web/app/mobile/tags/ui-header.tag         |  2 +-
 src/web/app/mobile/tags/ui-nav.tag            |  2 +-
 src/web/app/mobile/tags/ui.tag                |  8 +--
 src/web/app/mobile/tags/user-followers.tag    |  2 +-
 src/web/app/mobile/tags/user-following.tag    |  2 +-
 src/web/app/mobile/tags/user-timeline.tag     |  2 +-
 src/web/app/mobile/tags/user.tag              |  8 +--
 src/web/app/mobile/tags/users-list.tag        |  6 +-
 101 files changed, 423 insertions(+), 423 deletions(-)

diff --git a/src/web/app/auth/tags/form.tag b/src/web/app/auth/tags/form.tag
index b5ace7371..bb424d98c 100644
--- a/src/web/app/auth/tags/form.tag
+++ b/src/web/app/auth/tags/form.tag
@@ -111,13 +111,13 @@
 		this.session = this.opts.session
 		this.app = @session.app
 
-		cancel() {
+		this.cancel = () => {
 			this.api 'auth/deny' do
 				token: @session.token
 			.then =>
 				this.trigger('denied');
 
-		accept() {
+		this.accept = () => {
 			this.api 'auth/accept' do
 				token: @session.token
 			.then =>
diff --git a/src/web/app/auth/tags/index.tag b/src/web/app/auth/tags/index.tag
index a9f7828b9..0059fef20 100644
--- a/src/web/app/auth/tags/index.tag
+++ b/src/web/app/auth/tags/index.tag
@@ -127,7 +127,7 @@
 				this.state = 'fetch-session-error' 
 				this.update();
 
-		accepted() {
+		this.accepted = () => {
 			this.state = 'accepted' 
 			this.update();
 
diff --git a/src/web/app/common/tags/core-error.tag b/src/web/app/common/tags/core-error.tag
index b424c8abb..e74e205af 100644
--- a/src/web/app/common/tags/core-error.tag
+++ b/src/web/app/common/tags/core-error.tag
@@ -57,7 +57,7 @@
 
 	</style>
 	<script>
-		retry() {
+		this.retry = () => {
 			this.unmount();
 			this.opts.retry();
 		}
diff --git a/src/web/app/common/tags/messaging/form.tag b/src/web/app/common/tags/messaging/form.tag
index 4ae1706ff..8e74fbd35 100644
--- a/src/web/app/common/tags/messaging/form.tag
+++ b/src/web/app/common/tags/messaging/form.tag
@@ -119,7 +119,7 @@
 	<script>
 		this.mixin('api');
 
-		onpaste(e) {
+		this.onpaste = (e) => {
 			const data = e.clipboardData;
 			const items = data.items;
 			for (let i = 0; i < items.length; i++) {
@@ -130,17 +130,17 @@
 			}
 		}
 
-		onkeypress(e) {
+		this.onkeypress = (e) => {
 			if ((e.which == 10 || e.which == 13) && e.ctrlKey) {
 				this.send();
 			}
 		}
 
-		selectFile() {
+		this.selectFile = () => {
 			this.refs.file.click();
 		}
 
-		selectFileFromDrive() {
+		this.selectFileFromDrive = () => {
 			const browser = document.body.appendChild(document.createElement('mk-select-file-from-drive-window'));
 			const event = riot.observable();
 			riot.mount(browser, {
@@ -152,7 +152,7 @@
 			});
 		}
 
-		send() {
+		this.send = () => {
 			this.sending = true;
 			this.api('messaging/messages/create', {
 				user_id: this.opts.user.id,
@@ -166,7 +166,7 @@
 				this.update();
 			});
 
-		clear() {
+		this.clear = () => {
 			this.refs.text.value = '';
 			this.files = [];
 			this.update();
diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
index e9a031a2b..e7d110140 100644
--- a/src/web/app/common/tags/messaging/index.tag
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -305,7 +305,7 @@
 			});
 		}
 
-		search() {
+		this.search = () => {
 			const q = this.refs.search.value;
 			if (q == '') {
 				this.searchResult = [];
@@ -323,7 +323,7 @@
 				.catch (err) =>
 					console.error err
 
-		on-search-keydown(e) {
+		this.on-search-keydown = (e) => {
 			key = e.which
 			switch (key)
 				| 9, 40 => // Key[TAB] or Key[↓]
@@ -331,7 +331,7 @@
 					e.stopPropagation();
 					this.refs.search-result.childNodes[0].focus();
 
-		on-search-result-keydown(i, e) {
+		this.on-search-result-keydown = (i, e) => {
 			key = e.which
 			switch (key)
 				| 10, 13 => // Key[ENTER]
diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index a40258569..f04fd4638 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -128,18 +128,18 @@
 		this.mixin('api');
 		this.mixin('messaging-stream');
 
-		this.user = this.opts.user
-		this.init = true
-		this.sending = false
-		this.messages = []
+		this.user = this.opts.user;
+		this.init = true;
+		this.sending = false;
+		this.messages = [];
 
-		this.connection = new @MessagingStreamConnection this.I, @user.id
+		this.connection = new this.MessagingStreamConnection(this.I, this.user.id);
 
 		this.on('mount', () => {
-			@connection.event.on 'message' this.on-message
-			@connection.event.on 'read' this.on-read
+			this.connection.event.on('message' this.onMessage);
+			this.connection.event.on('read' this.onRead);
 
-			document.add-event-listener 'visibilitychange' this.on-visibilitychange
+			document.addEventListener 'visibilitychange' this.on-visibilitychange
 
 			this.api 'messaging/messages' do
 				user_id: @user.id
@@ -156,7 +156,7 @@
 			@connection.event.off 'read' this.on-read
 			@connection.close!
 
-			document.remove-event-listener 'visibilitychange' this.on-visibilitychange
+			document.removeEventListener 'visibilitychange' this.on-visibilitychange
 
 		this.on('update', () => {
 			@messages.for-each (message) =>
@@ -165,7 +165,7 @@
 				message._date = date
 				message._datetext = month + '月 ' + date + '日'
 
-		on-message(message) {
+		this.on-message = (message) => {
 			is-bottom = @is-bottom!
 
 			@messages.push message
@@ -182,7 +182,7 @@
 				// Notify
 				@notify '新しいメッセージがあります'
 
-		on-read(ids) {
+		this.on-read = (ids) => {
 			if not Array.isArray ids then ids = [ids]
 			ids.for-each (id) =>
 				if (@messages.some (x) => x.id == id)
@@ -190,15 +190,15 @@
 					@messages[exist].is_read = true
 					this.update();
 
-		is-bottom() {
+		this.is-bottom = () => {
 			current = this.root.scroll-top + this.root.offset-height
 			max = this.root.scroll-height
 			current > (max - 32)
 
-		scroll-to-bottom() {
+		this.scroll-to-bottom = () => {
 			this.root.scroll-top = this.root.scroll-height
 
-		notify(message) {
+		this.notify = (message) => {
 			n = document.createElement 'p' 
 			n.inner-HTML = '<i class="fa fa-arrow-circle-down"></i>' + message
 			n.onclick = =>
@@ -213,7 +213,7 @@
 				, 1000ms
 			, 4000ms
 
-		on-visibilitychange() {
+		this.on-visibilitychange = () => {
 			if document.hidden then return
 			@messages.for-each (message) =>
 				if message.user_id != this.I.id and not message.is_read
diff --git a/src/web/app/common/tags/poll-editor.tag b/src/web/app/common/tags/poll-editor.tag
index e35d8e136..9d9b28c76 100644
--- a/src/web/app/common/tags/poll-editor.tag
+++ b/src/web/app/common/tags/poll-editor.tag
@@ -88,26 +88,26 @@
 	<script>
 		this.choices = ['', ''];
 
-		oninput(i, e) {
+		this.oninput = (i, e) => {
 			this.choices[i] = e.target.value;
 		}
 
-		add() {
+		this.add = () => {
 			this.choices.push('');
 			this.update();
 			this.refs.choices.childNodes[this.choices.length - 1].childNodes[0].focus();
 		}
 
-		remove(i) {
+		this.remove = (i) => {
 			this.choices = this.choices.filter((_, _i) => _i != i);
 			this.update();
 		}
 
-		destroy() {
+		this.destroy = () => {
 			this.opts.ondestroy();
 		}
 
-		get() {
+		this.get = () => {
 			return {
 				choices: this.choices.filter(choice => choice != '')
 			}
diff --git a/src/web/app/common/tags/poll.tag b/src/web/app/common/tags/poll.tag
index c9209c3a3..6ddaf7759 100644
--- a/src/web/app/common/tags/poll.tag
+++ b/src/web/app/common/tags/poll.tag
@@ -76,11 +76,11 @@
 		this.isVoted = this.poll.choices.some(c => c.is_voted);
 		this.result = this.isVoted;
 
-		toggleResult() {
+		this.toggleResult = () => {
 			this.result = !this.result;
 		}
 
-		vote(id) {
+		this.vote = (id) => {
 			if (this.poll.choices.some(c => c.is_voted)) return;
 			this.api('posts/polls/vote', {
 				post_id: this.post.id,
diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag
index 4b5c844b7..97087e347 100644
--- a/src/web/app/common/tags/signin-history.tag
+++ b/src/web/app/common/tags/signin-history.tag
@@ -68,7 +68,7 @@
 		this.on('unmount', () => {
 			@stream.off 'signin' this.on-signin
 
-		on-signin(signin) {
+		this.on-signin = (signin) => {
 			@history.unshift signin
 			this.update();
 	</script>
diff --git a/src/web/app/common/tags/signin.tag b/src/web/app/common/tags/signin.tag
index 5cb63685f..e71795708 100644
--- a/src/web/app/common/tags/signin.tag
+++ b/src/web/app/common/tags/signin.tag
@@ -102,7 +102,7 @@
 		this.user = null;
 		this.signing = false;
 
-		oninput() {
+		this.oninput = () => {
 			this.api 'users/show' do
 				username: this.refs.username.value
 			.then (user) =>
@@ -110,7 +110,7 @@
 				this.trigger 'user' user
 				this.update();
 
-		onsubmit(e) {
+		this.onsubmit = (e) => {
 			e.preventDefault();
 
 			if this.refs.username.value == ''
diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag
index 55b1b7613..f8ac1c19c 100644
--- a/src/web/app/common/tags/signup.tag
+++ b/src/web/app/common/tags/signup.tag
@@ -199,7 +199,7 @@
 			head.appendChild script
 		});
 
-		on-change-username() {
+		this.on-change-username = () => {
 			username = this.refs.username.value
 
 			if username == ''
@@ -232,7 +232,7 @@
 					this.username-state = 'error' 
 					this.update();
 
-		on-change-password() {
+		this.on-change-password = () => {
 			password = this.refs.password.value
 
 			if password == ''
@@ -252,7 +252,7 @@
 
 			this.refs.password-metar.style.width = (strength * 100) + '%' 
 
-		on-change-password-retype() {
+		this.on-change-password-retype = () => {
 			password = this.refs.password.value
 			retyped-password = this.refs.password-retype.value
 
@@ -265,7 +265,7 @@
 			else
 				this.password-retype-state = 'not-match' 
 
-		onsubmit(e) {
+		this.onsubmit = (e) => {
 			e.preventDefault();
 
 			username = this.refs.username.value
diff --git a/src/web/app/common/tags/time.tag b/src/web/app/common/tags/time.tag
index 9bdb7f4cd..131113353 100644
--- a/src/web/app/common/tags/time.tag
+++ b/src/web/app/common/tags/time.tag
@@ -22,7 +22,7 @@
 			if @mode == 'relative' or @mode == 'detail' 
 				clear-interval @tickid
 
-		tick() {
+		this.tick = () => {
 			now = new Date!
 			ago = (now - @time) / 1000ms
 			this.relative = switch
diff --git a/src/web/app/common/tags/uploader.tag b/src/web/app/common/tags/uploader.tag
index 72f6eaa22..f6e99892a 100644
--- a/src/web/app/common/tags/uploader.tag
+++ b/src/web/app/common/tags/uploader.tag
@@ -145,7 +145,7 @@
 		this.uploads = []
 
 		
-		upload(file, folder) {
+		this.upload = (file, folder) => {
 			id = Math.random!
 
 			ctx =
diff --git a/src/web/app/desktop/tags/analog-clock.tag b/src/web/app/desktop/tags/analog-clock.tag
index 06896fe20..c1390be64 100644
--- a/src/web/app/desktop/tags/analog-clock.tag
+++ b/src/web/app/desktop/tags/analog-clock.tag
@@ -16,7 +16,7 @@
 		this.on('unmount', () => {
 			clear-interval @clock
 
-		draw() {
+		this.draw = () => {
 			now = new Date!
 			s = now.get-seconds!
 			m = now.get-minutes!
diff --git a/src/web/app/desktop/tags/autocomplete-suggestion.tag b/src/web/app/desktop/tags/autocomplete-suggestion.tag
index cf735255b..29ce938b8 100644
--- a/src/web/app/desktop/tags/autocomplete-suggestion.tag
+++ b/src/web/app/desktop/tags/autocomplete-suggestion.tag
@@ -89,11 +89,11 @@
 		this.select = -1
 
 		this.on('mount', () => {
-			@textarea.add-event-listener 'keydown' this.on-keydown
+			@textarea.addEventListener 'keydown' this.on-keydown
 
 			all = document.query-selector-all 'body *'
 			Array.prototype.for-each.call all, (el) =>
-				el.add-event-listener 'mousedown' @mousedown
+				el.addEventListener 'mousedown' @mousedown
 
 			this.api 'users/search_by_username' do
 				query: @q
@@ -106,20 +106,20 @@
 				console.error err
 
 		this.on('unmount', () => {
-			@textarea.remove-event-listener 'keydown' this.on-keydown
+			@textarea.removeEventListener 'keydown' this.on-keydown
 
 			all = document.query-selector-all 'body *'
 			Array.prototype.for-each.call all, (el) =>
-				el.remove-event-listener 'mousedown' @mousedown
+				el.removeEventListener 'mousedown' @mousedown
 
-		mousedown(e) {
+		this.mousedown = (e) => {
 			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 
-		on-click(e) {
+		this.on-click = (e) => {
 			@complete e.item
 
-		on-keydown(e) {
+		this.on-keydown = (e) => {
 			key = e.which
 			switch (key)
 				| 10, 13 => // Key[ENTER]
@@ -147,7 +147,7 @@
 				| _ =>
 					@close!
 
-		select-next() {
+		this.select-next = () => {
 			@select++
 
 			if @select >= @users.length
@@ -155,7 +155,7 @@
 
 			@apply-select!
 
-		select-prev() {
+		this.select-prev = () => {
 			@select--
 
 			if @select < 0
@@ -163,17 +163,17 @@
 
 			@apply-select!
 
-		apply-select() {
+		this.apply-select = () => {
 			this.refs.users.children.for-each (el) =>
 				el.remove-attribute 'data-selected' 
 
 			this.refs.users.children[@select].setAttribute 'data-selected' \true
 			this.refs.users.children[@select].focus();
 
-		complete(user) {
+		this.complete = (user) => {
 			this.opts.complete user
 
-		close() {
+		this.close = () => {
 			this.opts.close!
 
 		function contains(parent, child)
diff --git a/src/web/app/desktop/tags/big-follow-button.tag b/src/web/app/desktop/tags/big-follow-button.tag
index 6c87e8755..78ecbc2d6 100644
--- a/src/web/app/desktop/tags/big-follow-button.tag
+++ b/src/web/app/desktop/tags/big-follow-button.tag
@@ -91,17 +91,17 @@
 			@stream.off 'follow' this.on-stream-follow
 			@stream.off 'unfollow' this.on-stream-unfollow
 
-		on-stream-follow(user) {
+		this.on-stream-follow = (user) => {
 			if user.id == @user.id
 				this.user = user
 				this.update();
 
-		on-stream-unfollow(user) {
+		this.on-stream-unfollow = (user) => {
 			if user.id == @user.id
 				this.user = user
 				this.update();
 
-		onclick() {
+		this.onclick = () => {
 			this.wait = true
 			if @user.is_following
 				this.api 'following/delete' do
diff --git a/src/web/app/desktop/tags/contextmenu.tag b/src/web/app/desktop/tags/contextmenu.tag
index 0d8cb313a..400090c6c 100644
--- a/src/web/app/desktop/tags/contextmenu.tag
+++ b/src/web/app/desktop/tags/contextmenu.tag
@@ -94,19 +94,19 @@
 
 	</style>
 	<script>
-		this.root.add-event-listener 'contextmenu' (e) =>
+		this.root.addEventListener 'contextmenu' (e) =>
 			e.preventDefault();
 
-		mousedown(e) {
+		this.mousedown = (e) => {
 			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 			return false
 
-		open(pos) {
+		this.open = (pos) => {
 			all = document.query-selector-all 'body *'
 			Array.prototype.for-each.call all, (el) =>
-				el.add-event-listener 'mousedown' @mousedown
+				el.addEventListener 'mousedown' @mousedown
 			this.root.style.display = 'block' 
 			this.root.style.left = pos.x + 'px' 
 			this.root.style.top = pos.y + 'px' 
@@ -121,10 +121,10 @@
 				easing: 'linear' 
 			}
 
-		close() {
+		this.close = () => {
 			all = document.query-selector-all 'body *'
 			Array.prototype.for-each.call all, (el) =>
-				el.remove-event-listener 'mousedown' @mousedown
+				el.removeEventListener 'mousedown' @mousedown
 			this.trigger('closed');
 			this.unmount();
 
diff --git a/src/web/app/desktop/tags/crop-window.tag b/src/web/app/desktop/tags/crop-window.tag
index e022c76fa..45704a4b5 100644
--- a/src/web/app/desktop/tags/crop-window.tag
+++ b/src/web/app/desktop/tags/crop-window.tag
@@ -172,16 +172,16 @@
 				highlight: no
 				view-mode: 1
 
-		ok() {
+		this.ok = () => {
 			@cropper.get-cropped-canvas!.to-blob (blob) =>
 				this.trigger 'cropped' blob
 				this.refs.window.close!
 
-		skip() {
+		this.skip = () => {
 			this.trigger('skiped');
 			this.refs.window.close!
 
-		cancel() {
+		this.cancel = () => {
 			this.trigger('canceled');
 			this.refs.window.close!
 	</script>
diff --git a/src/web/app/desktop/tags/dialog.tag b/src/web/app/desktop/tags/dialog.tag
index a444ac18f..f163f99b8 100644
--- a/src/web/app/desktop/tags/dialog.tag
+++ b/src/web/app/desktop/tags/dialog.tag
@@ -114,7 +114,7 @@
 				easing: [ 0, 0.5, 0.5, 1 ]
 			}
 
-		close() {
+		this.close = () => {
 			this.refs.bg.style.pointer-events = 'none' 
 			Velocity this.refs.bg, 'finish' true
 			Velocity this.refs.bg, {
@@ -138,7 +138,7 @@
 					this.unmount();
 			}
 
-		bg-click() {
+		this.bg-click = () => {
 			if @can-through
 				if this.opts.on-through?
 					this.opts.on-through!
diff --git a/src/web/app/desktop/tags/donation.tag b/src/web/app/desktop/tags/donation.tag
index 9ce2ed819..0946e430d 100644
--- a/src/web/app/desktop/tags/donation.tag
+++ b/src/web/app/desktop/tags/donation.tag
@@ -50,7 +50,7 @@
 		this.mixin('api');
 		this.mixin('i');
 
-		close(e) {
+		this.close = (e) => {
 			e.preventDefault();
 			e.stopPropagation();
 
diff --git a/src/web/app/desktop/tags/drive/base-contextmenu.tag b/src/web/app/desktop/tags/drive/base-contextmenu.tag
index 7eb5fd3b9..9503e639d 100644
--- a/src/web/app/desktop/tags/drive/base-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/base-contextmenu.tag
@@ -20,18 +20,18 @@
 				this.trigger('closed');
 				this.unmount();
 
-		open(pos) {
+		this.open = (pos) => {
 			this.refs.ctx.open pos
 
-		create-folder() {
+		this.create-folder = () => {
 			this.browser.create-folder!
 			this.refs.ctx.close!
 
-		upload() {
+		this.upload = () => {
 			this.browser.select-local-file!
 			this.refs.ctx.close!
 
-		url-upload() {
+		this.url-upload = () => {
 			this.browser.url-upload!
 			this.refs.ctx.close!
 	</script>
diff --git a/src/web/app/desktop/tags/drive/browser-window.tag b/src/web/app/desktop/tags/drive/browser-window.tag
index c36726444..b5b2572d4 100644
--- a/src/web/app/desktop/tags/drive/browser-window.tag
+++ b/src/web/app/desktop/tags/drive/browser-window.tag
@@ -40,7 +40,7 @@
 				@update do
 					usage: info.usage / info.capacity * 100
 
-		close() {
+		this.close = () => {
 			this.refs.window.close!
 	</script>
 </mk-drive-browser-window>
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index 2a93afbb2..383da9018 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -289,27 +289,27 @@
 			@stream.off 'drive_folder_created' this.on-stream-drive-folder-created
 			@stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
 
-		on-stream-drive-file-created(file) {
+		this.on-stream-drive-file-created = (file) => {
 			@add-file file, true
 
-		on-stream-drive-file-updated(file) {
+		this.on-stream-drive-file-updated = (file) => {
 			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				@remove-file file
 			else
 				@add-file file, true
 
-		on-stream-drive-folder-created(folder) {
+		this.on-stream-drive-folder-created = (folder) => {
 			@add-folder folder, true
 
-		on-stream-drive-folder-updated(folder) {
+		this.on-stream-drive-folder-updated = (folder) => {
 			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
 				@remove-folder folder
 			else
 				@add-folder folder, true
 
-		onmousedown(e) {
+		this.onmousedown = (e) => {
 			if (contains this.refs.folders-container, e.target) or (contains this.refs.files-container, e.target)
 				return true
 
@@ -341,20 +341,20 @@
 					this.refs.selection.style.top = cursor-y + 'px' 
 
 			up = (e) =>
-				document.document-element.remove-event-listener 'mousemove' move
-				document.document-element.remove-event-listener 'mouseup' up
+				document.document-element.removeEventListener 'mousemove' move
+				document.document-element.removeEventListener 'mouseup' up
 
 				this.refs.selection.style.display = 'none' 
 
-			document.document-element.add-event-listener 'mousemove' move
-			document.document-element.add-event-listener 'mouseup' up
+			document.document-element.addEventListener 'mousemove' move
+			document.document-element.addEventListener 'mouseup' up
 
-		path-oncontextmenu(e) {
+		this.path-oncontextmenu = (e) => {
 			e.preventDefault();
 			e.stop-immediate-propagation!
 			return false
 
-		ondragover(e) {
+		this.ondragover = (e) => {
 			e.preventDefault();
 			e.stopPropagation();
 
@@ -371,15 +371,15 @@
 				e.dataTransfer.dropEffect = 'none' 
 			return false
 
-		ondragenter(e) {
+		this.ondragenter = (e) => {
 			e.preventDefault();
 			if !@is-drag-source
 				this.draghover = true
 
-		ondragleave(e) {
+		this.ondragleave = (e) => {
 			this.draghover = false
 
-		ondrop(e) {
+		this.ondrop = (e) => {
 			e.preventDefault();
 			e.stopPropagation();
 
@@ -438,7 +438,7 @@
 
 			return false
 
-		oncontextmenu(e) {
+		this.oncontextmenu = (e) => {
 			e.preventDefault();
 			e.stop-immediate-propagation!
 
@@ -452,10 +452,10 @@
 
 			return false
 
-		select-local-file() {
+		this.select-local-file = () => {
 			this.refs.file-input.click!
 
-		url-upload() {
+		this.url-upload = () => {
 			url <~ @input-dialog do
 				'URLアップロード'
 				'アップロードしたいファイルのURL'
@@ -473,7 +473,7 @@
 						text: 'OK' 
 					]
 
-		create-folder() {
+		this.create-folder = () => {
 			name <~ @input-dialog do
 				'フォルダー作成'
 				'フォルダー名'
@@ -488,26 +488,26 @@
 			.catch (err) =>
 				console.error err
 
-		change-file-input() {
+		this.change-file-input = () => {
 			files = this.refs.file-input.files
 			for i from 0 to files.length - 1
 				file = files.item i
 				@upload file, this.folder
 
-		upload(file, folder) {
+		this.upload = (file, folder) => {
 			if folder? and typeof folder == 'object' 
 				folder = folder.id
 			this.refs.uploader.upload file, folder
 
-		get-selection() {
+		this.get-selection = () => {
 			this.files.filter (file) -> file._selected
 
-		new-window(folder-id) {
+		this.new-window = (folder-id) => {
 			browser = document.body.appendChild document.createElement 'mk-drive-browser-window' 
 			riot.mount browser, do
 				folder: folder-id
 
-		move(target-folder) {
+		this.move = (target-folder) => {
 			if target-folder? and typeof target-folder == 'object' 
 				target-folder = target-folder.id
 
@@ -537,7 +537,7 @@
 			.catch (err, text-status) ->
 				console.error err
 
-		add-folder(folder, unshift = false) {
+		this.add-folder = (folder, unshift = false) => {
 			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
 				return
@@ -555,7 +555,7 @@
 
 			this.update();
 
-		add-file(file, unshift = false) {
+		this.add-file = (file, unshift = false) => {
 			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				return
@@ -573,26 +573,26 @@
 
 			this.update();
 
-		remove-folder(folder) {
+		this.remove-folder = (folder) => {
 			if typeof folder == 'object' 
 				folder = folder.id
 			this.folders = this.folders.filter (f) -> f.id != folder
 			this.update();
 
-		remove-file(file) {
+		this.remove-file = (file) => {
 			if typeof file == 'object' 
 				file = file.id
 			this.files = this.files.filter (f) -> f.id != file
 			this.update();
 
-		go-root() {
+		this.go-root = () => {
 			if this.folder != null
 				this.folder = null
 				this.hierarchy-folders = []
 				this.update();
 				@load!
 
-		load() {
+		this.load = () => {
 			this.folders = []
 			this.files = []
 			this.more-folders = false
diff --git a/src/web/app/desktop/tags/drive/file-contextmenu.tag b/src/web/app/desktop/tags/drive/file-contextmenu.tag
index 06e708562..e8d75ccd4 100644
--- a/src/web/app/desktop/tags/drive/file-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/file-contextmenu.tag
@@ -54,10 +54,10 @@
 				this.trigger('closed');
 				this.unmount();
 
-		open(pos) {
+		this.open = (pos) => {
 			this.refs.ctx.open pos
 
-		rename() {
+		this.rename = () => {
 			this.refs.ctx.close!
 
 			name <~ @input-dialog do
@@ -73,25 +73,25 @@
 			.catch (err) =>
 				console.error err
 
-		copy-url() {
+		this.copy-url = () => {
 			@NotImplementedException!
 
-		download() {
+		this.download = () => {
 			this.refs.ctx.close!
 
-		set-avatar() {
+		this.set-avatar = () => {
 			this.refs.ctx.close!
 			@update-avatar this.I, null, this.file
 
-		set-banner() {
+		this.set-banner = () => {
 			this.refs.ctx.close!
 			@update-banner this.I, null, this.file
 
-		set-wallpaper() {
+		this.set-wallpaper = () => {
 			this.refs.ctx.close!
 			@update-wallpaper this.I, null, this.file
 
-		add-app() {
+		this.add-app = () => {
 			@NotImplementedException!
 	</script>
 </mk-drive-browser-file-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/file.tag b/src/web/app/desktop/tags/drive/file.tag
index d41c5279f..e0e9beb21 100644
--- a/src/web/app/desktop/tags/drive/file.tag
+++ b/src/web/app/desktop/tags/drive/file.tag
@@ -155,7 +155,7 @@
 
 		this.is-contextmenu-showing = false
 
-		onclick() {
+		this.onclick = () => {
 			if this.browser.multiple
 				if this.file._selected?
 					this.file._selected = !this.file._selected
@@ -171,7 +171,7 @@
 					this.file._selected = true
 					this.browser.trigger 'change-selection' this.file
 
-		oncontextmenu(e) {
+		this.oncontextmenu = (e) => {
 			e.preventDefault();
 			e.stop-immediate-propagation!
 
@@ -190,7 +190,7 @@
 				this.update();
 			return false
 
-		ondragstart(e) {
+		this.ondragstart = (e) => {
 			e.dataTransfer.effect-allowed = 'move' 
 			e.dataTransfer.set-data 'text' JSON.stringify do
 				type: 'file' 
@@ -202,7 +202,7 @@
 			// (=あなたの子供が、ドラッグを開始しましたよ)
 			this.browser.is-drag-source = true
 
-		ondragend(e) {
+		this.ondragend = (e) => {
 			this.is-dragging = false
 			this.browser.is-drag-source = false
 	</script>
diff --git a/src/web/app/desktop/tags/drive/folder-contextmenu.tag b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
index df094d0bc..92fb5457c 100644
--- a/src/web/app/desktop/tags/drive/folder-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
@@ -24,30 +24,30 @@
 		this.browser = this.opts.browser
 		this.folder = this.opts.folder
 
-		open(pos) {
+		this.open = (pos) => {
 			this.refs.ctx.open pos
 
 			this.refs.ctx.on('closed', () => {
 				this.trigger('closed');
 				this.unmount();
 
-		move() {
+		this.move = () => {
 			this.browser.move this.folder.id
 			this.refs.ctx.close!
 
-		new-window() {
+		this.new-window = () => {
 			this.browser.new-window this.folder.id
 			this.refs.ctx.close!
 
-		create-folder() {
+		this.create-folder = () => {
 			this.browser.create-folder!
 			this.refs.ctx.close!
 
-		upload() {
+		this.upload = () => {
 			this.browser.select-lcoal-file!
 			this.refs.ctx.close!
 
-		rename() {
+		this.rename = () => {
 			this.refs.ctx.close!
 
 			name <~ @input-dialog do
diff --git a/src/web/app/desktop/tags/drive/folder.tag b/src/web/app/desktop/tags/drive/folder.tag
index 2d58ddefc..25524a80d 100644
--- a/src/web/app/desktop/tags/drive/folder.tag
+++ b/src/web/app/desktop/tags/drive/folder.tag
@@ -61,16 +61,16 @@
 		this.draghover = false
 		this.is-contextmenu-showing = false
 
-		onclick() {
+		this.onclick = () => {
 			this.browser.move this.folder
 
-		onmouseover() {
+		this.onmouseover = () => {
 			this.hover = true
 
-		onmouseout() {
+		this.onmouseout = () => {
 			this.hover = false
 
-		ondragover(e) {
+		this.ondragover = (e) => {
 			e.preventDefault();
 			e.stopPropagation();
 
@@ -86,14 +86,14 @@
 				e.dataTransfer.dropEffect = 'none' 
 			return false
 
-		ondragenter() {
+		this.ondragenter = () => {
 			if !@is-dragging
 				this.draghover = true
 
-		ondragleave() {
+		this.ondragleave = () => {
 			this.draghover = false
 
-		ondrop(e) {
+		this.ondrop = (e) => {
 			e.stopPropagation();
 			this.draghover = false
 
@@ -146,7 +146,7 @@
 
 			return false
 
-		ondragstart(e) {
+		this.ondragstart = (e) => {
 			e.dataTransfer.effect-allowed = 'move' 
 			e.dataTransfer.set-data 'text' JSON.stringify do
 				type: 'folder' 
@@ -157,11 +157,11 @@
 			// (=あなたの子供が、ドラッグを開始しましたよ)
 			this.browser.is-drag-source = true
 
-		ondragend(e) {
+		this.ondragend = (e) => {
 			this.is-dragging = false
 			this.browser.is-drag-source = false
 
-		oncontextmenu(e) {
+		this.oncontextmenu = (e) => {
 			e.preventDefault();
 			e.stop-immediate-propagation!
 
diff --git a/src/web/app/desktop/tags/drive/nav-folder.tag b/src/web/app/desktop/tags/drive/nav-folder.tag
index 8f8f00783..5a620d76c 100644
--- a/src/web/app/desktop/tags/drive/nav-folder.tag
+++ b/src/web/app/desktop/tags/drive/nav-folder.tag
@@ -16,16 +16,16 @@
 
 		this.hover = false
 
-		onclick() {
+		this.onclick = () => {
 			this.browser.move this.folder
 
-		onmouseover() {
+		this.onmouseover = () => {
 			this.hover = true
 
-		onmouseout() {
+		this.onmouseout = () => {
 			this.hover = false
 
-		ondragover(e) {
+		this.ondragover = (e) => {
 			e.preventDefault();
 			e.stopPropagation();
 
@@ -39,15 +39,15 @@
 				e.dataTransfer.dropEffect = 'move' 
 			return false
 
-		ondragenter() {
+		this.ondragenter = () => {
 			if this.folder != null or this.browser.folder != null
 				this.draghover = true
 
-		ondragleave() {
+		this.ondragleave = () => {
 			if this.folder != null or this.browser.folder != null
 				this.draghover = false
 
-		ondrop(e) {
+		this.ondrop = (e) => {
 			e.stopPropagation();
 			this.draghover = false
 
diff --git a/src/web/app/desktop/tags/follow-button.tag b/src/web/app/desktop/tags/follow-button.tag
index 575c99c70..87284cbc0 100644
--- a/src/web/app/desktop/tags/follow-button.tag
+++ b/src/web/app/desktop/tags/follow-button.tag
@@ -88,17 +88,17 @@
 			@stream.off 'follow' this.on-stream-follow
 			@stream.off 'unfollow' this.on-stream-unfollow
 
-		on-stream-follow(user) {
+		this.on-stream-follow = (user) => {
 			if user.id == @user.id
 				this.user = user
 				this.update();
 
-		on-stream-unfollow(user) {
+		this.on-stream-unfollow = (user) => {
 			if user.id == @user.id
 				this.user = user
 				this.update();
 
-		onclick() {
+		this.onclick = () => {
 			this.wait = true
 			if @user.is_following
 				this.api 'following/delete' do
diff --git a/src/web/app/desktop/tags/following-setuper.tag b/src/web/app/desktop/tags/following-setuper.tag
index 5faba3e65..fd1aa4bc8 100644
--- a/src/web/app/desktop/tags/following-setuper.tag
+++ b/src/web/app/desktop/tags/following-setuper.tag
@@ -135,7 +135,7 @@
 		this.on('mount', () => {
 			@load!
 
-		load() {
+		this.load = () => {
 			this.loading = true
 			this.users = null
 			this.update();
@@ -150,14 +150,14 @@
 			.catch (err, text-status) ->
 				console.error err
 
-		refresh() {
+		this.refresh = () => {
 			if @users.length < @limit
 				this.page = 0
 			else
 				@page++
 			@load!
 
-		close() {
+		this.close = () => {
 			this.unmount();
 	</script>
 </mk-following-setuper>
diff --git a/src/web/app/desktop/tags/go-top.tag b/src/web/app/desktop/tags/go-top.tag
index 42efaf2f2..cb75c0480 100644
--- a/src/web/app/desktop/tags/go-top.tag
+++ b/src/web/app/desktop/tags/go-top.tag
@@ -1,11 +1,11 @@
 <mk-go-top>
 	<button class="hidden" title="一番上へ"><i class="fa fa-angle-up"></i></button>
 	<script>
-		window.add-event-listener 'load' this.on-scroll
-		window.add-event-listener 'scroll' this.on-scroll
-		window.add-event-listener 'resize' this.on-scroll
+		window.addEventListener 'load' this.on-scroll
+		window.addEventListener 'scroll' this.on-scroll
+		window.addEventListener 'resize' this.on-scroll
 
-		on-scroll() {
+		this.on-scroll = () => {
 			if $ window .scroll-top! > 500px
 				@remove-class 'hidden' 
 			else
diff --git a/src/web/app/desktop/tags/home-widgets/calendar.tag b/src/web/app/desktop/tags/home-widgets/calendar.tag
index 81378b8a7..fb8d88962 100644
--- a/src/web/app/desktop/tags/home-widgets/calendar.tag
+++ b/src/web/app/desktop/tags/home-widgets/calendar.tag
@@ -106,7 +106,7 @@
 
 	</style>
 	<script>
-		draw() {
+		this.draw = () => {
 			now = new Date!
 			nd = now.get-date!
 			nm = now.get-month!
diff --git a/src/web/app/desktop/tags/home-widgets/mentions.tag b/src/web/app/desktop/tags/home-widgets/mentions.tag
index 149a30238..492eacb17 100644
--- a/src/web/app/desktop/tags/home-widgets/mentions.tag
+++ b/src/web/app/desktop/tags/home-widgets/mentions.tag
@@ -55,23 +55,23 @@
 		this.mode = 'all' 
 
 		this.on('mount', () => {
-			document.add-event-listener 'keydown' this.on-document-keydown
-			window.add-event-listener 'scroll' this.on-scroll
+			document.addEventListener 'keydown' this.on-document-keydown
+			window.addEventListener 'scroll' this.on-scroll
 
 			@fetch =>
 				this.trigger('loaded');
 
 		this.on('unmount', () => {
-			document.remove-event-listener 'keydown' this.on-document-keydown
-			window.remove-event-listener 'scroll' this.on-scroll
+			document.removeEventListener 'keydown' this.on-document-keydown
+			window.removeEventListener 'scroll' this.on-scroll
 
-		on-document-keydown(e) {
+		this.on-document-keydown = (e) => {
 			tag = e.target.tag-name.to-lower-case!
 			if tag != 'input' and tag != 'textarea' 
 				if e.which == 84 // t
 					this.refs.timeline.focus();
 
-		fetch(cb) {
+		this.fetch = (cb) => {
 			this.api 'posts/mentions' do
 				following: @mode == 'following' 
 			.then (posts) =>
@@ -84,7 +84,7 @@
 				console.error err
 				if cb? then cb!
 
-		more() {
+		this.more = () => {
 			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
 				return
 			this.more-loading = true
@@ -99,12 +99,12 @@
 			.catch (err) =>
 				console.error err
 
-		on-scroll() {
+		this.on-scroll = () => {
 			current = window.scroll-y + window.inner-height
 			if current > document.body.offset-height - 8
 				@more!
 
-		set-mode(mode) {
+		this.set-mode = (mode) => {
 			@update do
 				mode: mode
 			@fetch!
diff --git a/src/web/app/desktop/tags/home-widgets/notifications.tag b/src/web/app/desktop/tags/home-widgets/notifications.tag
index 4ed7f6378..12520e95a 100644
--- a/src/web/app/desktop/tags/home-widgets/notifications.tag
+++ b/src/web/app/desktop/tags/home-widgets/notifications.tag
@@ -43,7 +43,7 @@
 
 	</style>
 	<script>
-		settings() {
+		this.settings = () => {
 			w = riot.mount document.body.appendChild document.createElement 'mk-settings-window' .0
 			w.switch 'notification' 
 	</script>
diff --git a/src/web/app/desktop/tags/home-widgets/photo-stream.tag b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
index 9b7756108..f7a80f40a 100644
--- a/src/web/app/desktop/tags/home-widgets/photo-stream.tag
+++ b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
@@ -77,7 +77,7 @@
 		this.on('unmount', () => {
 			@stream.off 'drive_file_created' this.on-stream-drive-file-created
 
-		on-stream-drive-file-created(file) {
+		this.on-stream-drive-file-created = (file) => {
 			if /^image\/.+$/.test file.type
 				@images.unshift file
 				if @images.length > 9
diff --git a/src/web/app/desktop/tags/home-widgets/profile.tag b/src/web/app/desktop/tags/home-widgets/profile.tag
index 3cff6b682..72b2c18c3 100644
--- a/src/web/app/desktop/tags/home-widgets/profile.tag
+++ b/src/web/app/desktop/tags/home-widgets/profile.tag
@@ -46,10 +46,10 @@
 		this.mixin('update-avatar');
 		this.mixin('update-banner');
 
-		set-avatar() {
+		this.set-avatar = () => {
 			@update-avatar this.I
 
-		set-banner() {
+		this.set-banner = () => {
 			@update-banner this.I
 	</script>
 </mk-profile-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/rss-reader.tag b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
index 6778ea3bb..2ced342a4 100644
--- a/src/web/app/desktop/tags/home-widgets/rss-reader.tag
+++ b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
@@ -78,7 +78,7 @@
 		this.on('unmount', () => {
 			clear-interval @clock
 
-		fetch() {
+		this.fetch = () => {
 			this.api CONFIG.url + '/api:rss' do
 				url: @url
 			.then (feed) =>
@@ -88,7 +88,7 @@
 			.catch (err) ->
 				console.error err
 
-		settings() {
+		this.settings = () => {
 			@NotImplementedException!
 	</script>
 </mk-rss-reader-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index 1fcf4ab57..dbeac5eaf 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -46,8 +46,8 @@
 			@stream.on 'follow' this.on-stream-follow
 			@stream.on 'unfollow' this.on-stream-unfollow
 
-			document.add-event-listener 'keydown' this.on-document-keydown
-			window.add-event-listener 'scroll' this.on-scroll
+			document.addEventListener 'keydown' this.on-document-keydown
+			window.addEventListener 'scroll' this.on-scroll
 
 			@load =>
 				this.trigger('loaded');
@@ -57,16 +57,16 @@
 			@stream.off 'follow' this.on-stream-follow
 			@stream.off 'unfollow' this.on-stream-unfollow
 
-			document.remove-event-listener 'keydown' this.on-document-keydown
-			window.remove-event-listener 'scroll' this.on-scroll
+			document.removeEventListener 'keydown' this.on-document-keydown
+			window.removeEventListener 'scroll' this.on-scroll
 
-		on-document-keydown(e) {
+		this.on-document-keydown = (e) => {
 			tag = e.target.tag-name.to-lower-case!
 			if tag != 'input' and tag != 'textarea' 
 				if e.which == 84 // t
 					this.refs.timeline.focus();
 
-		load(cb) {
+		this.load = (cb) => {
 			this.api 'posts/timeline' 
 			.then (posts) =>
 				this.is-loading = false
@@ -78,7 +78,7 @@
 				console.error err
 				if cb? then cb!
 
-		more() {
+		this.more = () => {
 			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
 				return
 			this.more-loading = true
@@ -92,18 +92,18 @@
 			.catch (err) =>
 				console.error err
 
-		on-stream-post(post) {
+		this.on-stream-post = (post) => {
 			this.is-empty = false
 			this.update();
 			this.refs.timeline.add-post post
 
-		on-stream-follow() {
+		this.on-stream-follow = () => {
 			@load!
 
-		on-stream-unfollow() {
+		this.on-stream-unfollow = () => {
 			@load!
 
-		on-scroll() {
+		this.on-scroll = () => {
 			current = window.scroll-y + window.inner-height
 			if current > document.body.offset-height - 8
 				@more!
diff --git a/src/web/app/desktop/tags/home-widgets/tips.tag b/src/web/app/desktop/tags/home-widgets/tips.tag
index c28514bbf..08e1b1737 100644
--- a/src/web/app/desktop/tags/home-widgets/tips.tag
+++ b/src/web/app/desktop/tags/home-widgets/tips.tag
@@ -48,11 +48,11 @@
 		this.on('unmount', () => {
 			clear-interval @clock
 
-		set() {
+		this.set = () => {
 			this.refs.text.innerHTML = @tips[Math.floor Math.random! * @tips.length]
 			this.update();
 
-		change() {
+		this.change = () => {
 			Velocity this.refs.tip, {
 				opacity: 0
 			} {
diff --git a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
index b2ec4ba88..f2a8a7476 100644
--- a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
+++ b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
@@ -128,7 +128,7 @@
 		this.on('unmount', () => {
 			clear-interval @clock
 
-		fetch(quiet = false) {
+		this.fetch = (quiet = false) => {
 			this.loading = true
 			this.users = null
 			if not quiet then this.update();
@@ -142,7 +142,7 @@
 			.catch (err, text-status) ->
 				console.error err
 
-		refresh() {
+		this.refresh = () => {
 			if @users.length < @limit
 				this.page = 0
 			else
diff --git a/src/web/app/desktop/tags/image-dialog.tag b/src/web/app/desktop/tags/image-dialog.tag
index ae42a968b..9a8a0e3b7 100644
--- a/src/web/app/desktop/tags/image-dialog.tag
+++ b/src/web/app/desktop/tags/image-dialog.tag
@@ -53,7 +53,7 @@
 			// easing: 'ease-out' 
 			#}
 
-		close() {
+		this.close = () => {
 			Velocity this.root, {
 				opacity: 0
 			} {
diff --git a/src/web/app/desktop/tags/images-viewer.tag b/src/web/app/desktop/tags/images-viewer.tag
index 7d552bc9f..84190d34d 100644
--- a/src/web/app/desktop/tags/images-viewer.tag
+++ b/src/web/app/desktop/tags/images-viewer.tag
@@ -29,7 +29,7 @@
 		this.images = this.opts.images
 		this.image = @images.0
 
-		mousemove(e) {
+		this.mousemove = (e) => {
 			rect = this.refs.view.get-bounding-client-rect!
 			mouse-x = e.client-x - rect.left
 			mouse-y = e.client-y - rect.top
@@ -37,7 +37,7 @@
 			yp = mouse-y / this.refs.view.offset-height * 100
 			this.refs.view.style.background-position = xp + '% ' + yp + '%'
 
-		click() {
+		this.click = () => {
 			dialog = document.body.appendChild document.createElement 'mk-image-dialog' 
 			riot.mount dialog, do
 				image: @image
diff --git a/src/web/app/desktop/tags/input-dialog.tag b/src/web/app/desktop/tags/input-dialog.tag
index c2cf09330..b5aefcd16 100644
--- a/src/web/app/desktop/tags/input-dialog.tag
+++ b/src/web/app/desktop/tags/input-dialog.tag
@@ -139,16 +139,16 @@
 			this.refs.window.on('closed', () => {
 				this.unmount();
 
-		cancel() {
+		this.cancel = () => {
 			this.done = false
 			this.refs.window.close!
 
-		ok() {
+		this.ok = () => {
 			if not @allow-empty and @text.value == '' then return
 			this.done = true
 			this.refs.window.close!
 
-		on-keydown(e) {
+		this.on-keydown = (e) => {
 			if e.which == 13 // Enter
 				e.preventDefault();
 				e.stopPropagation();
diff --git a/src/web/app/desktop/tags/notifications.tag b/src/web/app/desktop/tags/notifications.tag
index 7ef13ad7e..39a33e410 100644
--- a/src/web/app/desktop/tags/notifications.tag
+++ b/src/web/app/desktop/tags/notifications.tag
@@ -199,7 +199,7 @@
 		this.on('unmount', () => {
 			@stream.off 'notification' this.on-notification
 
-		on-notification(notification) {
+		this.on-notification = (notification) => {
 			@notifications.unshift notification
 			this.update();
 
diff --git a/src/web/app/desktop/tags/pages/entrance.tag b/src/web/app/desktop/tags/pages/entrance.tag
index 227aec388..486f83f9d 100644
--- a/src/web/app/desktop/tags/pages/entrance.tag
+++ b/src/web/app/desktop/tags/pages/entrance.tag
@@ -65,15 +65,15 @@
 	<script>
 		this.mode = 'signin' 
 
-		signup() {
+		this.signup = () => {
 			this.mode = 'signup' 
 			this.update();
 
-		signin() {
+		this.signin = () => {
 			this.mode = 'signin' 
 			this.update();
 
-		introduction() {
+		this.introduction = () => {
 			this.mode = 'introduction' 
 			this.update();
 	</script>
diff --git a/src/web/app/desktop/tags/pages/entrance/signin.tag b/src/web/app/desktop/tags/pages/entrance/signin.tag
index 67a449a73..b620c88b8 100644
--- a/src/web/app/desktop/tags/pages/entrance/signin.tag
+++ b/src/web/app/desktop/tags/pages/entrance/signin.tag
@@ -124,7 +124,7 @@
 				@update do
 					user: user
 
-		introduction() {
+		this.introduction = () => {
 			this.parent.introduction!
 	</script>
 </mk-entrance-signin>
diff --git a/src/web/app/desktop/tags/pages/home.tag b/src/web/app/desktop/tags/pages/home.tag
index 0f0bc4e37..3dd0b69d8 100644
--- a/src/web/app/desktop/tags/pages/home.tag
+++ b/src/web/app/desktop/tags/pages/home.tag
@@ -28,18 +28,18 @@
 			document.title = 'Misskey'
 			this.Progress.start();
 			@stream.on 'post' this.on-stream-post
-			document.add-event-listener 'visibilitychange' @window-on-visibilitychange, false
+			document.addEventListener 'visibilitychange' @window-on-visibilitychange, false
 
 		this.on('unmount', () => {
 			@stream.off 'post' this.on-stream-post
-			document.remove-event-listener 'visibilitychange' @window-on-visibilitychange
+			document.removeEventListener 'visibilitychange' @window-on-visibilitychange
 
-		on-stream-post(post) {
+		this.on-stream-post = (post) => {
 			if document.hidden and post.user_id !== this.I.id
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
-		window-on-visibilitychange() {
+		this.window-on-visibilitychange = () => {
 			if !document.hidden
 				this.unread-count = 0
 				document.title = 'Misskey'
diff --git a/src/web/app/desktop/tags/post-detail-sub.tag b/src/web/app/desktop/tags/post-detail-sub.tag
index ccb475c76..1a6dbe069 100644
--- a/src/web/app/desktop/tags/post-detail-sub.tag
+++ b/src/web/app/desktop/tags/post-detail-sub.tag
@@ -123,7 +123,7 @@
 					if e.tag-name == 'MK-URL' 
 						riot.mount e
 
-		like() {
+		this.like = () => {
 			if @post.is_liked
 				this.api 'posts/likes/delete' do
 					post_id: @post.id
diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag
index 0443ff883..c835521ad 100644
--- a/src/web/app/desktop/tags/post-detail.tag
+++ b/src/web/app/desktop/tags/post-detail.tag
@@ -398,17 +398,17 @@
 
 				this.update();
 
-		reply() {
+		this.reply = () => {
 			form = document.body.appendChild document.createElement 'mk-post-form-window' 
 			riot.mount form, do
 				reply: @p
 
-		repost() {
+		this.repost = () => {
 			form = document.body.appendChild document.createElement 'mk-repost-form-window' 
 			riot.mount form, do
 				post: @p
 
-		like() {
+		this.like = () => {
 			if @p.is_liked
 				this.api 'posts/likes/delete' do
 					post_id: @p.id
@@ -422,7 +422,7 @@
 					@p.is_liked = true
 					this.update();
 
-		load-context() {
+		this.load-context = () => {
 			this.loading-context = true
 
 			// Get context
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index b1c06143b..d49feba14 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -335,16 +335,16 @@
 		this.on('unmount', () => {
 			@autocomplete.detach!
 
-		focus() {
+		this.focus = () => {
 			this.refs.text.focus();
 
-		clear() {
+		this.clear = () => {
 			this.refs.text.value = ''
 			this.files = []
 			this.trigger('change-files');
 			this.update();
 
-		ondragover(e) {
+		this.ondragover = (e) => {
 			e.stopPropagation();
 			this.draghover = true
 			// ドラッグされてきたものがファイルだったら
@@ -354,13 +354,13 @@
 				e.dataTransfer.dropEffect = 'move' 
 			return false
 
-		ondragenter(e) {
+		this.ondragenter = (e) => {
 			this.draghover = true
 
-		ondragleave(e) {
+		this.ondragleave = (e) => {
 			this.draghover = false
 
-		ondrop(e) {
+		this.ondrop = (e) => {
 			e.preventDefault();
 			e.stopPropagation();
 			this.draghover = false
@@ -388,11 +388,11 @@
 
 			return false
 
-		onkeydown(e) {
+		this.onkeydown = (e) => {
 			if (e.which == 10 || e.which == 13) && (e.ctrlKey || e.meta-key)
 				@post!
 
-		onpaste(e) {
+		this.onpaste = (e) => {
 			data = e.clipboardData
 			items = data.items
 			for i from 0 to items.length - 1
@@ -401,26 +401,26 @@
 					| 'file' =>
 						@upload item.getAsFile();
 
-		select-file() {
+		this.select-file = () => {
 			this.refs.file.click!
 
-		select-file-from-drive() {
+		this.select-file-from-drive = () => {
 			browser = document.body.appendChild document.createElement 'mk-select-file-from-drive-window' 
 			i = riot.mount browser, do
 				multiple: true
 			i[0].one 'selected' (files) =>
 				files.for-each @add-file
 
-		change-file() {
+		this.change-file = () => {
 			files = this.refs.file.files
 			for i from 0 to files.length - 1
 				file = files.item i
 				@upload file
 
-		upload(file) {
+		this.upload = (file) => {
 			this.refs.uploader.upload file
 
-		add-file(file) {
+		this.add-file = (file) => {
 			file._remove = =>
 				this.files = this.files.filter (x) -> x.id != file.id
 				this.trigger 'change-files' this.files
@@ -430,14 +430,14 @@
 			this.trigger 'change-files' this.files
 			this.update();
 
-		add-poll() {
+		this.add-poll = () => {
 			this.poll = true
 
-		on-poll-destroyed() {
+		this.on-poll-destroyed = () => {
 			@update do
 				poll: false
 
-		post(e) {
+		this.post = (e) => {
 			this.wait = true
 
 			files = if this.files? and this.files.length > 0
@@ -459,7 +459,7 @@
 				this.wait = false
 				this.update();
 
-		cat() {
+		this.cat = () => {
 			this.refs.text.value = this.refs.text.value + get-cat!
 	</script>
 </mk-post-form>
diff --git a/src/web/app/desktop/tags/progress-dialog.tag b/src/web/app/desktop/tags/progress-dialog.tag
index bb5dea8b4..da0ed16d7 100644
--- a/src/web/app/desktop/tags/progress-dialog.tag
+++ b/src/web/app/desktop/tags/progress-dialog.tag
@@ -83,12 +83,12 @@
 			this.refs.window.on('closed', () => {
 				this.unmount();
 
-		update-progress(value, max) {
+		this.update-progress = (value, max) => {
 			this.value = parse-int value, 10
 			this.max = parse-int max, 10
 			this.update();
 
-		close() {
+		this.close = () => {
 			this.refs.window.close!
 	</script>
 </mk-progress-dialog>
diff --git a/src/web/app/desktop/tags/repost-form-window.tag b/src/web/app/desktop/tags/repost-form-window.tag
index d66f98bb8..7af67094b 100644
--- a/src/web/app/desktop/tags/repost-form-window.tag
+++ b/src/web/app/desktop/tags/repost-form-window.tag
@@ -12,7 +12,7 @@
 
 	</style>
 	<script>
-		on-document-keydown(e) {
+		this.on-document-keydown = (e) => {
 			tag = e.target.tag-name.to-lower-case!
 			if tag != 'input' and tag != 'textarea' 
 				if e.which == 27 // Esc
@@ -25,12 +25,12 @@
 			this.refs.window.refs.form.on('posted', () => {
 				this.refs.window.close!
 
-			document.add-event-listener 'keydown' this.on-document-keydown
+			document.addEventListener 'keydown' this.on-document-keydown
 
 			this.refs.window.on('closed', () => {
 				this.unmount();
 
 		this.on('unmount', () => {
-			document.remove-event-listener 'keydown' this.on-document-keydown
+			document.removeEventListener 'keydown' this.on-document-keydown
 	</script>
 </mk-repost-form-window>
diff --git a/src/web/app/desktop/tags/repost-form.tag b/src/web/app/desktop/tags/repost-form.tag
index 58ef564ba..319b42dd0 100644
--- a/src/web/app/desktop/tags/repost-form.tag
+++ b/src/web/app/desktop/tags/repost-form.tag
@@ -120,10 +120,10 @@
 		this.wait = false
 		this.quote = false
 
-		cancel() {
+		this.cancel = () => {
 			this.trigger('cancel');
 
-		ok() {
+		this.ok = () => {
 			this.wait = true
 			this.api 'posts/create' do
 				repost_id: this.opts.post.id
@@ -138,7 +138,7 @@
 				this.wait = false
 				this.update();
 
-		onquote() {
+		this.onquote = () => {
 			this.quote = true
 	</script>
 </mk-repost-form>
diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag
index a61a0a061..a450e8a02 100644
--- a/src/web/app/desktop/tags/search-posts.tag
+++ b/src/web/app/desktop/tags/search-posts.tag
@@ -38,8 +38,8 @@
 		this.page = 0
 
 		this.on('mount', () => {
-			document.add-event-listener 'keydown' this.on-document-keydown
-			window.add-event-listener 'scroll' this.on-scroll
+			document.addEventListener 'keydown' this.on-document-keydown
+			window.addEventListener 'scroll' this.on-scroll
 
 			this.api 'posts/search' do
 				query: @query
@@ -53,16 +53,16 @@
 				console.error err
 
 		this.on('unmount', () => {
-			document.remove-event-listener 'keydown' this.on-document-keydown
-			window.remove-event-listener 'scroll' this.on-scroll
+			document.removeEventListener 'keydown' this.on-document-keydown
+			window.removeEventListener 'scroll' this.on-scroll
 
-		on-document-keydown(e) {
+		this.on-document-keydown = (e) => {
 			tag = e.target.tag-name.to-lower-case!
 			if tag != 'input' and tag != 'textarea' 
 				if e.which == 84 // t
 					this.refs.timeline.focus();
 
-		more() {
+		this.more = () => {
 			if @more-loading or @is-loading or @timeline.posts.length == 0
 				return
 			this.more-loading = true
@@ -78,7 +78,7 @@
 			.catch (err) =>
 				console.error err
 
-		on-scroll() {
+		this.on-scroll = () => {
 			current = window.scroll-y + window.inner-height
 			if current > document.body.offset-height - 16 // 遊び
 				@more!
diff --git a/src/web/app/desktop/tags/select-file-from-drive-window.tag b/src/web/app/desktop/tags/select-file-from-drive-window.tag
index c8fc02d22..6979a5521 100644
--- a/src/web/app/desktop/tags/select-file-from-drive-window.tag
+++ b/src/web/app/desktop/tags/select-file-from-drive-window.tag
@@ -148,13 +148,13 @@
 			this.refs.window.on('closed', () => {
 				this.unmount();
 
-		close() {
+		this.close = () => {
 			this.refs.window.close!
 
-		upload() {
+		this.upload = () => {
 			this.refs.window.refs.browser.select-local-file!
 
-		ok() {
+		this.ok = () => {
 			this.trigger 'selected' this.file
 			this.refs.window.close!
 	</script>
diff --git a/src/web/app/desktop/tags/set-avatar-suggestion.tag b/src/web/app/desktop/tags/set-avatar-suggestion.tag
index e398a6ed2..ba44a7a33 100644
--- a/src/web/app/desktop/tags/set-avatar-suggestion.tag
+++ b/src/web/app/desktop/tags/set-avatar-suggestion.tag
@@ -34,10 +34,10 @@
 		this.mixin('i');
 		this.mixin('update-avatar');
 
-		set() {
+		this.set = () => {
 			@update-avatar this.I
 
-		close(e) {
+		this.close = (e) => {
 			e.preventDefault();
 			e.stopPropagation();
 			this.unmount();
diff --git a/src/web/app/desktop/tags/set-banner-suggestion.tag b/src/web/app/desktop/tags/set-banner-suggestion.tag
index 73c67a02b..fa735e4e4 100644
--- a/src/web/app/desktop/tags/set-banner-suggestion.tag
+++ b/src/web/app/desktop/tags/set-banner-suggestion.tag
@@ -34,10 +34,10 @@
 		this.mixin('i');
 		this.mixin('update-banner');
 
-		set() {
+		this.set = () => {
 			@update-banner this.I
 
-		close(e) {
+		this.close = (e) => {
 			e.preventDefault();
 			e.stopPropagation();
 			this.unmount();
diff --git a/src/web/app/desktop/tags/settings-window.tag b/src/web/app/desktop/tags/settings-window.tag
index 4ffc5f225..89219fccf 100644
--- a/src/web/app/desktop/tags/settings-window.tag
+++ b/src/web/app/desktop/tags/settings-window.tag
@@ -19,7 +19,7 @@
 			this.refs.window.on('closed', () => {
 				this.unmount();
 
-		close() {
+		this.close = () => {
 			this.refs.window.close!
 	</script>
 </mk-settings-window>
diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag
index e67a1b11a..e4a83738e 100644
--- a/src/web/app/desktop/tags/settings.tag
+++ b/src/web/app/desktop/tags/settings.tag
@@ -205,13 +205,13 @@
 
 		this.page = 'account' 
 
-		set-page(page) {
+		this.set-page = (page) => {
 			this.page = page
 
-		avatar() {
+		this.avatar = () => {
 			@update-avatar this.I
 
-		update-account() {
+		this.update-account = () => {
 			this.api 'i/update' do
 				name: this.refs.account-name.value
 				location: this.refs.account-location.value
@@ -222,19 +222,19 @@
 			.catch (err) =>
 				console.error err
 
-		update-cache() {
+		this.update-cache = () => {
 			this.I.data.cache = !this.I.data.cache
 			this.api 'i/appdata/set' do
 				data: JSON.stringify do
 					cache: this.I.data.cache
 
-		update-debug() {
+		this.update-debug = () => {
 			this.I.data.debug = !this.I.data.debug
 			this.api 'i/appdata/set' do
 				data: JSON.stringify do
 					debug: this.I.data.debug
 
-		update-nya() {
+		this.update-nya = () => {
 			this.I.data.nya = !this.I.data.nya
 			this.api 'i/appdata/set' do
 				data: JSON.stringify do
diff --git a/src/web/app/desktop/tags/timeline-post.tag b/src/web/app/desktop/tags/timeline-post.tag
index ea1bed257..5efc05063 100644
--- a/src/web/app/desktop/tags/timeline-post.tag
+++ b/src/web/app/desktop/tags/timeline-post.tag
@@ -349,17 +349,17 @@
 						riot.mount @preview, do
 							url: t.content
 
-		reply() {
+		this.reply = () => {
 			form = document.body.appendChild document.createElement 'mk-post-form-window' 
 			riot.mount form, do
 				reply: @p
 
-		repost() {
+		this.repost = () => {
 			form = document.body.appendChild document.createElement 'mk-repost-form-window' 
 			riot.mount form, do
 				post: @p
 
-		like() {
+		this.like = () => {
 			if @p.is_liked
 				this.api 'posts/likes/delete' do
 					post_id: @p.id
@@ -373,11 +373,11 @@
 					@p.is_liked = true
 					this.update();
 
-		toggle-detail() {
+		this.toggle-detail = () => {
 			this.is-detail-opened = !@is-detail-opened
 			this.update();
 
-		on-key-down(e) {
+		this.on-key-down = (e) => {
 			should-be-cancel = true
 			switch
 			| e.which == 38 or e.which == 74 or (e.which == 9 and e.shift-key) => // ↑, j or Shift+Tab
diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag
index 5967c2efd..ebc6249c6 100644
--- a/src/web/app/desktop/tags/timeline.tag
+++ b/src/web/app/desktop/tags/timeline.tag
@@ -46,24 +46,24 @@
 	<script>
 		this.posts = []
 
-		set-posts(posts) {
+		this.set-posts = (posts) => {
 			this.posts = posts
 			this.update();
 
-		prepend-posts(posts) {
+		this.prepend-posts = (posts) => {
 			posts.for-each (post) =>
 				@posts.push post
 				this.update();
 
-		add-post(post) {
+		this.add-post = (post) => {
 			@posts.unshift post
 			this.update();
 
-		clear() {
+		this.clear = () => {
 			this.posts = []
 			this.update();
 
-		focus() {
+		this.focus = () => {
 			this.root.children.0.focus();
 
 		this.on('update', () => {
@@ -73,7 +73,7 @@
 				post._date = date
 				post._datetext = month + '月 ' + date + '日'
 
-		tail() {
+		this.tail = () => {
 			@posts[@posts.length - 1]
 	</script>
 </mk-timeline>
diff --git a/src/web/app/desktop/tags/ui-header-account.tag b/src/web/app/desktop/tags/ui-header-account.tag
index fa3f60a61..e6ededc75 100644
--- a/src/web/app/desktop/tags/ui-header-account.tag
+++ b/src/web/app/desktop/tags/ui-header-account.tag
@@ -167,37 +167,37 @@
 		this.on('before-unmount', () => {
 			@close!
 
-		toggle() {
+		this.toggle = () => {
 			if @is-open
 				@close!
 			else
 				@open!
 
-		open() {
+		this.open = () => {
 			this.is-open = true
 			this.update();
 			all = document.query-selector-all 'body *'
 			Array.prototype.for-each.call all, (el) =>
-				el.add-event-listener 'mousedown' @mousedown
+				el.addEventListener 'mousedown' @mousedown
 
-		close() {
+		this.close = () => {
 			this.is-open = false
 			this.update();
 			all = document.query-selector-all 'body *'
 			Array.prototype.for-each.call all, (el) =>
-				el.remove-event-listener 'mousedown' @mousedown
+				el.removeEventListener 'mousedown' @mousedown
 
-		mousedown(e) {
+		this.mousedown = (e) => {
 			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
 			return false
 
-		drive() {
+		this.drive = () => {
 			@close!
 			riot.mount document.body.appendChild document.createElement 'mk-drive-browser-window' 
 
-		settings() {
+		this.settings = () => {
 			@close!
 			riot.mount document.body.appendChild document.createElement 'mk-settings-window' 
 
diff --git a/src/web/app/desktop/tags/ui-header-clock.tag b/src/web/app/desktop/tags/ui-header-clock.tag
index 339951fb6..5b42cefbb 100644
--- a/src/web/app/desktop/tags/ui-header-clock.tag
+++ b/src/web/app/desktop/tags/ui-header-clock.tag
@@ -58,7 +58,7 @@
 
 	</style>
 	<script>
-		draw() {
+		this.draw = () => {
 			now = new Date!
 
 			yyyy = now.get-full-year!
diff --git a/src/web/app/desktop/tags/ui-header-nav.tag b/src/web/app/desktop/tags/ui-header-nav.tag
index 8f710600f..88607d6a5 100644
--- a/src/web/app/desktop/tags/ui-header-nav.tag
+++ b/src/web/app/desktop/tags/ui-header-nav.tag
@@ -98,15 +98,15 @@
 				@stream.off 'read_all_messaging_messages' this.on-read-all-messaging-messages
 				@stream.off 'unread_messaging_message' this.on-unread-messaging-message
 
-			on-read-all-messaging-messages() {
+			this.on-read-all-messaging-messages = () => {
 				this.has-unread-messaging-messages = false
 				this.update();
 
-			on-unread-messaging-message() {
+			this.on-unread-messaging-message = () => {
 				this.has-unread-messaging-messages = true
 				this.update();
 
-			messaging() {
+			this.messaging = () => {
 				riot.mount document.body.appendChild document.createElement 'mk-messaging-window' 
 		</script>
 	</ul>
diff --git a/src/web/app/desktop/tags/ui-header-notifications.tag b/src/web/app/desktop/tags/ui-header-notifications.tag
index 1768f915e..0a355e022 100644
--- a/src/web/app/desktop/tags/ui-header-notifications.tag
+++ b/src/web/app/desktop/tags/ui-header-notifications.tag
@@ -77,27 +77,27 @@
 	<script>
 		this.is-open = false
 
-		toggle() {
+		this.toggle = () => {
 			if @is-open
 				@close!
 			else
 				@open!
 
-		open() {
+		this.open = () => {
 			this.is-open = true
 			this.update();
 			all = document.query-selector-all 'body *'
 			Array.prototype.for-each.call all, (el) =>
-				el.add-event-listener 'mousedown' @mousedown
+				el.addEventListener 'mousedown' @mousedown
 
-		close() {
+		this.close = () => {
 			this.is-open = false
 			this.update();
 			all = document.query-selector-all 'body *'
 			Array.prototype.for-each.call all, (el) =>
-				el.remove-event-listener 'mousedown' @mousedown
+				el.removeEventListener 'mousedown' @mousedown
 
-		mousedown(e) {
+		this.mousedown = (e) => {
 			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
 				@close!
diff --git a/src/web/app/desktop/tags/ui-header-post-button.tag b/src/web/app/desktop/tags/ui-header-post-button.tag
index 3d391ed2e..3f339beb6 100644
--- a/src/web/app/desktop/tags/ui-header-post-button.tag
+++ b/src/web/app/desktop/tags/ui-header-post-button.tag
@@ -35,7 +35,7 @@
 
 	</style>
 	<script>
-		post(e) {
+		this.post = (e) => {
 			this.parent.parent.open-post-form!
 	</script>
 </mk-ui-header-post-button>
diff --git a/src/web/app/desktop/tags/ui-header-search.tag b/src/web/app/desktop/tags/ui-header-search.tag
index 69d2dd732..cc8ca2ae0 100644
--- a/src/web/app/desktop/tags/ui-header-search.tag
+++ b/src/web/app/desktop/tags/ui-header-search.tag
@@ -34,7 +34,7 @@
 	<script>
 		this.mixin('page');
 
-		onsubmit(e) {
+		this.onsubmit = (e) => {
 			e.preventDefault();
 			@page '/search:' + this.refs.q.value
 	</script>
diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag
index 1ecb0f570..1e2cba35b 100644
--- a/src/web/app/desktop/tags/ui.tag
+++ b/src/web/app/desktop/tags/ui.tag
@@ -14,20 +14,20 @@
 	<script>
 		this.mixin('i');
 
-		open-post-form() {
+		this.open-post-form = () => {
 			riot.mount document.body.appendChild document.createElement 'mk-post-form-window' 
 
-		set-root-layout() {
+		this.set-root-layout = () => {
 			this.root.style.padding-top = this.refs.header.root.client-height + 'px' 
 
 		this.on('mount', () => {
 			@set-root-layout!
-			document.add-event-listener 'keydown' this.onkeydown
+			document.addEventListener 'keydown' this.onkeydown
 
 		this.on('unmount', () => {
-			document.remove-event-listener 'keydown' this.onkeydown
+			document.removeEventListener 'keydown' this.onkeydown
 
-		onkeydown(e) {
+		this.onkeydown = (e) => {
 			tag = e.target.tag-name.to-lower-case!
 			if tag != 'input' and tag != 'textarea' 
 				if e.which == 80 or e.which == 78 // p or n
diff --git a/src/web/app/desktop/tags/user-followers.tag b/src/web/app/desktop/tags/user-followers.tag
index 0ae29a209..53c3c8985 100644
--- a/src/web/app/desktop/tags/user-followers.tag
+++ b/src/web/app/desktop/tags/user-followers.tag
@@ -11,7 +11,7 @@
 
 		this.user = this.opts.user
 
-		fetch(iknow, limit, cursor, cb) {
+		this.fetch = (iknow, limit, cursor, cb) => {
 			this.api 'users/followers' do
 				user_id: @user.id
 				iknow: iknow
diff --git a/src/web/app/desktop/tags/user-following.tag b/src/web/app/desktop/tags/user-following.tag
index f640ee7b6..a8f9ccb89 100644
--- a/src/web/app/desktop/tags/user-following.tag
+++ b/src/web/app/desktop/tags/user-following.tag
@@ -11,7 +11,7 @@
 
 		this.user = this.opts.user
 
-		fetch(iknow, limit, cursor, cb) {
+		this.fetch = (iknow, limit, cursor, cb) => {
 			this.api 'users/following' do
 				user_id: @user.id
 				iknow: iknow
diff --git a/src/web/app/desktop/tags/user-header.tag b/src/web/app/desktop/tags/user-header.tag
index a2ed28b4f..ff37b334e 100644
--- a/src/web/app/desktop/tags/user-header.tag
+++ b/src/web/app/desktop/tags/user-header.tag
@@ -111,16 +111,16 @@
 		this.user = this.opts.user
 
 		this.on('mount', () => {
-			window.add-event-listener 'load' @scroll
-			window.add-event-listener 'scroll' @scroll
-			window.add-event-listener 'resize' @scroll
+			window.addEventListener 'load' @scroll
+			window.addEventListener 'scroll' @scroll
+			window.addEventListener 'resize' @scroll
 
 		this.on('unmount', () => {
-			window.remove-event-listener 'load' @scroll
-			window.remove-event-listener 'scroll' @scroll
-			window.remove-event-listener 'resize' @scroll
+			window.removeEventListener 'load' @scroll
+			window.removeEventListener 'scroll' @scroll
+			window.removeEventListener 'resize' @scroll
 
-		scroll() {
+		this.scroll = () => {
 			top = window.scroll-y
 			height = 280px
 
@@ -131,7 +131,7 @@
 			if blur <= 10
 				this.refs.banner.style.filter = 'blur(' + blur + 'px)'
 
-		on-update-banner() {
+		this.on-update-banner = () => {
 			if not @SIGNIN or this.I.id != @user.id
 				return
 
diff --git a/src/web/app/desktop/tags/user-preview.tag b/src/web/app/desktop/tags/user-preview.tag
index d17f7557d..00da1d8f1 100644
--- a/src/web/app/desktop/tags/user-preview.tag
+++ b/src/web/app/desktop/tags/user-preview.tag
@@ -130,7 +130,7 @@
 				easing: 'ease-out' 
 			}
 
-		close() {
+		this.close = () => {
 			Velocity this.root, {
 				opacity: 0
 				'margin-top': '-8px' 
diff --git a/src/web/app/desktop/tags/user-profile.tag b/src/web/app/desktop/tags/user-profile.tag
index a94f50c7b..b613aa968 100644
--- a/src/web/app/desktop/tags/user-profile.tag
+++ b/src/web/app/desktop/tags/user-profile.tag
@@ -86,12 +86,12 @@
 
 		this.user = this.opts.user
 
-		show-following() {
+		this.show-following = () => {
 			window = document.body.appendChild document.createElement 'mk-user-following-window' 
 			riot.mount window, do
 				user: @user
 
-		show-followers() {
+		this.show-followers = () => {
 			window = document.body.appendChild document.createElement 'mk-user-followers-window' 
 			riot.mount window, do
 				user: @user
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index b8e39b730..ab82b2677 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -59,9 +59,9 @@
 		this.mode = 'default' 
 
 		this.on('mount', () => {
-			document.add-event-listener 'visibilitychange' @window-on-visibilitychange, false
-			document.add-event-listener 'keydown' this.on-document-keydown
-			window.add-event-listener 'scroll' this.on-scroll
+			document.addEventListener 'visibilitychange' @window-on-visibilitychange, false
+			document.addEventListener 'keydown' this.on-document-keydown
+			window.addEventListener 'scroll' this.on-scroll
 
 			@user-promise.then (user) =>
 				this.user = user
@@ -71,17 +71,17 @@
 					this.trigger('loaded');
 
 		this.on('unmount', () => {
-			document.remove-event-listener 'visibilitychange' @window-on-visibilitychange
-			document.remove-event-listener 'keydown' this.on-document-keydown
-			window.remove-event-listener 'scroll' this.on-scroll
+			document.removeEventListener 'visibilitychange' @window-on-visibilitychange
+			document.removeEventListener 'keydown' this.on-document-keydown
+			window.removeEventListener 'scroll' this.on-scroll
 
-		on-document-keydown(e) {
+		this.on-document-keydown = (e) => {
 			tag = e.target.tag-name.to-lower-case!
 			if tag != 'input' and tag != 'textarea' 
 				if e.which == 84 // t
 					this.refs.timeline.focus();
 
-		fetch(cb) {
+		this.fetch = (cb) => {
 			this.api 'users/posts' do
 				user_id: @user.id
 				with_replies: @mode == 'with-replies' 
@@ -95,7 +95,7 @@
 				console.error err
 				if cb? then cb!
 
-		more() {
+		this.more = () => {
 			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
 				return
 			this.more-loading = true
@@ -111,7 +111,7 @@
 			.catch (err) =>
 				console.error err
 
-		on-stream-post(post) {
+		this.on-stream-post = (post) => {
 			this.is-empty = false
 			this.update();
 			this.refs.timeline.add-post post
@@ -120,17 +120,17 @@
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
-		window-on-visibilitychange() {
+		this.window-on-visibilitychange = () => {
 			if !document.hidden
 				this.unread-count = 0
 				document.title = 'Misskey'
 
-		on-scroll() {
+		this.on-scroll = () => {
 			current = window.scroll-y + window.inner-height
 			if current > document.body.offset-height - 16 // 遊び
 				@more!
 
-		set-mode(mode) {
+		this.set-mode = (mode) => {
 			@update do
 				mode: mode
 			@fetch!
diff --git a/src/web/app/desktop/tags/users-list.tag b/src/web/app/desktop/tags/users-list.tag
index af0f35d63..9fd123952 100644
--- a/src/web/app/desktop/tags/users-list.tag
+++ b/src/web/app/desktop/tags/users-list.tag
@@ -100,7 +100,7 @@
 			@fetch =>
 				this.trigger('loaded');
 
-		fetch(cb) {
+		this.fetch = (cb) => {
 			this.fetching = true
 			this.update();
 			obj <~ this.opts.fetch do
@@ -113,7 +113,7 @@
 			this.update();
 			if cb? then cb!
 
-		more() {
+		this.more = () => {
 			this.more-fetching = true
 			this.update();
 			obj <~ this.opts.fetch do
@@ -125,7 +125,7 @@
 			this.more-fetching = false
 			this.update();
 
-		set-mode(mode) {
+		this.set-mode = (mode) => {
 			@update do
 				mode: mode
 
diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index 71084f8b5..81011e9f5 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -207,17 +207,17 @@
 			this.refs.main.style.top = '15%' 
 			this.refs.main.style.left = (window.inner-width / 2) - (this.refs.main.offset-width / 2) + 'px' 
 
-			this.refs.header.add-event-listener 'contextmenu' (e) =>
+			this.refs.header.addEventListener 'contextmenu' (e) =>
 				e.preventDefault();
 
-			window.add-event-listener 'resize' this.on-browser-resize
+			window.addEventListener 'resize' this.on-browser-resize
 
 			@open!
 
 		this.on('unmount', () => {
-			window.remove-event-listener 'resize' this.on-browser-resize
+			window.removeEventListener 'resize' this.on-browser-resize
 
-		on-browser-resize() {
+		this.on-browser-resize = () => {
 			position = this.refs.main.get-bounding-client-rect!
 			browser-width = window.inner-width
 			browser-height = window.inner-height
@@ -236,7 +236,7 @@
 			if position.top + window-height > browser-height
 				this.refs.main.style.top = browser-height - window-height + 'px' 
 
-		open() {
+		this.open = () => {
 			this.trigger('opening');
 
 			@top!
@@ -270,7 +270,7 @@
 				this.trigger('opened');
 			, 300ms
 
-		close() {
+		this.close = () => {
 			this.trigger('closing');
 
 			if @is-modal
@@ -300,7 +300,7 @@
 			, 300ms
 
 		// 最前面へ移動します
-		top() {
+		this.top = () => {
 			z = 0
 
 			ws = document.query-selector-all 'mk-window' 
@@ -314,20 +314,20 @@
 				this.refs.main.style.z-index = z + 1
 				if @is-modal then this.refs.bg.style.z-index = z + 1
 
-		repel-move(e) {
+		this.repel-move = (e) => {
 			e.stopPropagation();
 			return true
 
-		bg-click() {
+		this.bg-click = () => {
 			if @can-close
 				@close!
 
-		on-body-mousedown(e) {
+		this.on-body-mousedown = (e) => {
 			@top!
 			true
 
 		// ヘッダー掴み時
-		on-header-mousedown(e) {
+		this.on-header-mousedown = (e) => {
 			e.preventDefault();
 
 			if not contains this.refs.main, document.active-element
@@ -369,7 +369,7 @@
 				this.refs.main.style.top = move-top + 'px' 
 
 		// 上ハンドル掴み時
-		on-top-handle-mousedown(e) {
+		this.on-top-handle-mousedown = (e) => {
 			e.preventDefault();
 
 			base = e.client-y
@@ -391,7 +391,7 @@
 					@apply-transform-top 0
 
 		// 右ハンドル掴み時
-		on-right-handle-mousedown(e) {
+		this.on-right-handle-mousedown = (e) => {
 			e.preventDefault();
 
 			base = e.client-x
@@ -411,7 +411,7 @@
 					@apply-transform-width browser-width - left
 
 		// 下ハンドル掴み時
-		on-bottom-handle-mousedown(e) {
+		this.on-bottom-handle-mousedown = (e) => {
 			e.preventDefault();
 
 			base = e.client-y
@@ -431,7 +431,7 @@
 					@apply-transform-height browser-height - top
 
 		// 左ハンドル掴み時
-		on-left-handle-mousedown(e) {
+		this.on-left-handle-mousedown = (e) => {
 			e.preventDefault();
 
 			base = e.client-x
@@ -453,55 +453,55 @@
 					@apply-transform-left 0
 
 		// 左上ハンドル掴み時
-		on-top-left-handle-mousedown(e) {
+		this.on-top-left-handle-mousedown = (e) => {
 			this.on-top-handle-mousedown e
 			this.on-left-handle-mousedown e
 
 		// 右上ハンドル掴み時
-		on-top-right-handle-mousedown(e) {
+		this.on-top-right-handle-mousedown = (e) => {
 			this.on-top-handle-mousedown e
 			this.on-right-handle-mousedown e
 
 		// 右下ハンドル掴み時
-		on-bottom-right-handle-mousedown(e) {
+		this.on-bottom-right-handle-mousedown = (e) => {
 			this.on-bottom-handle-mousedown e
 			this.on-right-handle-mousedown e
 
 		// 左下ハンドル掴み時
-		on-bottom-left-handle-mousedown(e) {
+		this.on-bottom-left-handle-mousedown = (e) => {
 			this.on-bottom-handle-mousedown e
 			this.on-left-handle-mousedown e
 
 		// 高さを適用
-		apply-transform-height(height) {
+		this.apply-transform-height = (height) => {
 			this.refs.main.style.height = height + 'px' 
 
 		// 幅を適用
-		apply-transform-width(width) {
+		this.apply-transform-width = (width) => {
 			this.refs.main.style.width = width + 'px' 
 
 		// Y座標を適用
-		apply-transform-top(top) {
+		this.apply-transform-top = (top) => {
 			this.refs.main.style.top = top + 'px' 
 
 		// X座標を適用
-		apply-transform-left(left) {
+		this.apply-transform-left = (left) => {
 			this.refs.main.style.left = left + 'px' 
 
 		function drag-listen fn
-			window.add-event-listener 'mousemove'  fn
-			window.add-event-listener 'mouseleave' drag-clear.bind null fn
-			window.add-event-listener 'mouseup'    drag-clear.bind null fn
+			window.addEventListener 'mousemove'  fn
+			window.addEventListener 'mouseleave' drag-clear.bind null fn
+			window.addEventListener 'mouseup'    drag-clear.bind null fn
 
 		function drag-clear fn
-			window.remove-event-listener 'mousemove'  fn
-			window.remove-event-listener 'mouseleave' drag-clear
-			window.remove-event-listener 'mouseup'    drag-clear
+			window.removeEventListener 'mousemove'  fn
+			window.removeEventListener 'mouseleave' drag-clear
+			window.removeEventListener 'mouseup'    drag-clear
 
-		ondragover(e) {
+		this.ondragover = (e) => {
 			e.dataTransfer.dropEffect = 'none' 
 
-		on-keydown(e) {
+		this.on-keydown = (e) => {
 			if e.which == 27 // Esc
 				if @can-close
 					e.preventDefault();
diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag
index 84e099612..2718bcd5d 100644
--- a/src/web/app/dev/tags/new-app-form.tag
+++ b/src/web/app/dev/tags/new-app-form.tag
@@ -182,7 +182,7 @@
 
 		this.nid-state = null
 
-		on-change-nid() {
+		this.on-change-nid = () => {
 			nid = this.refs.nid.value
 
 			if nid == ''
@@ -215,7 +215,7 @@
 					this.nid-state = 'error' 
 					this.update();
 
-		onsubmit() {
+		this.onsubmit = () => {
 			name = this.refs.name.value
 			nid = this.refs.nid.value
 			description = this.refs.description.value
diff --git a/src/web/app/mobile/tags/drive-selector.tag b/src/web/app/mobile/tags/drive-selector.tag
index ce9bdd2b5..873c49154 100644
--- a/src/web/app/mobile/tags/drive-selector.tag
+++ b/src/web/app/mobile/tags/drive-selector.tag
@@ -63,11 +63,11 @@
 				this.files = files
 				this.update();
 
-		cancel() {
+		this.cancel = () => {
 			this.trigger('canceled');
 			this.unmount();
 
-		ok() {
+		this.ok = () => {
 			this.trigger 'selected' this.files
 			this.unmount();
 	</script>
diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag
index ddaf60061..6daa50c26 100644
--- a/src/web/app/mobile/tags/drive.tag
+++ b/src/web/app/mobile/tags/drive.tag
@@ -167,20 +167,20 @@
 			@stream.off 'drive_folder_created' this.on-stream-drive-folder-created
 			@stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
 
-		on-stream-drive-file-created(file) {
+		this.on-stream-drive-file-created = (file) => {
 			@add-file file, true
 
-		on-stream-drive-file-updated(file) {
+		this.on-stream-drive-file-updated = (file) => {
 			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				@remove-file file
 			else
 				@add-file file, true
 
-		on-stream-drive-folder-created(folder) {
+		this.on-stream-drive-folder-created = (folder) => {
 			@add-folder folder, true
 
-		on-stream-drive-folder-updated(folder) {
+		this.on-stream-drive-folder-updated = (folder) => {
 			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
 				@remove-folder folder
@@ -190,10 +190,10 @@
 		@_move = (ev) =>
 			@move ev.item.folder
 
-		move(target-folder) {
+		this.move = (target-folder) => {
 			@cd target-folder
 
-		cd(target-folder, silent = false) {
+		this.cd = (target-folder, silent = false) => {
 			this.file = null
 
 			if target-folder? and typeof target-folder == 'object' 
@@ -226,7 +226,7 @@
 			.catch (err, text-status) ->
 				console.error err
 
-		add-folder(folder, unshift = false) {
+		this.add-folder = (folder, unshift = false) => {
 			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
 				return
@@ -241,7 +241,7 @@
 
 			this.update();
 
-		add-file(file, unshift = false) {
+		this.add-file = (file, unshift = false) => {
 			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				return
@@ -259,19 +259,19 @@
 
 			this.update();
 
-		remove-folder(folder) {
+		this.remove-folder = (folder) => {
 			if typeof folder == 'object' 
 				folder = folder.id
 			this.folders = this.folders.filter (f) -> f.id != folder
 			this.update();
 
-		remove-file(file) {
+		this.remove-file = (file) => {
 			if typeof file == 'object' 
 				file = file.id
 			this.files = this.files.filter (f) -> f.id != file
 			this.update();
 
-		go-root() {
+		this.go-root = () => {
 			if this.folder != null or this.file != null
 				this.file = null
 				this.folder = null
@@ -280,7 +280,7 @@
 				this.trigger('move-root');
 				@load!
 
-		load() {
+		this.load = () => {
 			this.folders = []
 			this.files = []
 			this.more-folders = false
@@ -337,11 +337,11 @@
 					flag := true
 					this.trigger('load-mid');
 
-		choose-file(file) {
+		this.choose-file = (file) => {
 			if @is-select-mode
 				exist = @selected-files.some (f) => f.id == file.id
 				if exist
-					selected-files(@selected-files.filter (f) { f.id != file.id)
+					this.selected-files = (@selected-files.filter (f) => { f.id != file.id)
 				else
 					@selected-files.push file
 				this.update();
@@ -349,7 +349,7 @@
 			else
 				@cf file
 
-		cf(file, silent = false) {
+		this.cf = (file, silent = false) => {
 			if typeof file == 'object' 
 				file = file.id
 
diff --git a/src/web/app/mobile/tags/drive/file-viewer.tag b/src/web/app/mobile/tags/drive/file-viewer.tag
index eff41ab85..5f1380ae8 100644
--- a/src/web/app/mobile/tags/drive/file-viewer.tag
+++ b/src/web/app/mobile/tags/drive/file-viewer.tag
@@ -188,7 +188,7 @@
 		this.file = this.opts.file
 		this.kind = this.file.type.split '/' .0
 
-		rename() {
+		this.rename = () => {
 			name = window.prompt '名前を変更' this.file.name
 			if name? and name != '' and name != this.file.name
 				this.api 'drive/files/update' do
diff --git a/src/web/app/mobile/tags/drive/file.tag b/src/web/app/mobile/tags/drive/file.tag
index c83134919..77b5b220a 100644
--- a/src/web/app/mobile/tags/drive/file.tag
+++ b/src/web/app/mobile/tags/drive/file.tag
@@ -131,7 +131,7 @@
 		this.browser.on('change-selected', (selects) => {
 			this.is-selected = selects.some (f) => f.id == this.file.id
 
-		onclick() {
+		this.onclick = () => {
 			this.browser.choose-file this.file
 	</script>
 </mk-drive-file>
diff --git a/src/web/app/mobile/tags/drive/folder.tag b/src/web/app/mobile/tags/drive/folder.tag
index c536fed9d..4c4727a30 100644
--- a/src/web/app/mobile/tags/drive/folder.tag
+++ b/src/web/app/mobile/tags/drive/folder.tag
@@ -40,7 +40,7 @@
 		this.browser = this.parent
 		this.folder = this.opts.folder
 
-		onclick() {
+		this.onclick = () => {
 			this.browser.move this.folder
 	</script>
 </mk-drive-folder>
diff --git a/src/web/app/mobile/tags/follow-button.tag b/src/web/app/mobile/tags/follow-button.tag
index 99936530c..36447f3ac 100644
--- a/src/web/app/mobile/tags/follow-button.tag
+++ b/src/web/app/mobile/tags/follow-button.tag
@@ -69,17 +69,17 @@
 			@stream.off 'follow' this.on-stream-follow
 			@stream.off 'unfollow' this.on-stream-unfollow
 
-		on-stream-follow(user) {
+		this.on-stream-follow = (user) => {
 			if user.id == @user.id
 				this.user = user
 				this.update();
 
-		on-stream-unfollow(user) {
+		this.on-stream-unfollow = (user) => {
 			if user.id == @user.id
 				this.user = user
 				this.update();
 
-		onclick() {
+		this.onclick = () => {
 			this.wait = true
 			if @user.is_following
 				this.api 'following/delete' do
diff --git a/src/web/app/mobile/tags/home-timeline.tag b/src/web/app/mobile/tags/home-timeline.tag
index 98c3a0821..322ba8f93 100644
--- a/src/web/app/mobile/tags/home-timeline.tag
+++ b/src/web/app/mobile/tags/home-timeline.tag
@@ -25,19 +25,19 @@
 			@stream.off 'follow' this.on-stream-follow
 			@stream.off 'unfollow' this.on-stream-unfollow
 
-		more() {
+		this.more = () => {
 			this.api 'posts/timeline' do
 				max_id: this.refs.timeline.tail!.id
 
-		on-stream-post(post) {
+		this.on-stream-post = (post) => {
 			this.is-empty = false
 			this.update();
 			this.refs.timeline.add-post post
 
-		on-stream-follow() {
+		this.on-stream-follow = () => {
 			@fetch!
 
-		on-stream-unfollow() {
+		this.on-stream-unfollow = () => {
 			@fetch!
 	</script>
 </mk-home-timeline>
diff --git a/src/web/app/mobile/tags/images-viewer.tag b/src/web/app/mobile/tags/images-viewer.tag
index 6ff03ba63..ad02850e3 100644
--- a/src/web/app/mobile/tags/images-viewer.tag
+++ b/src/web/app/mobile/tags/images-viewer.tag
@@ -21,7 +21,7 @@
 		this.images = this.opts.images
 		this.image = @images.0
 
-		click() {
+		this.click = () => {
 			window.open @image.url
 	</script>
 </mk-images-viewer>
diff --git a/src/web/app/mobile/tags/notifications.tag b/src/web/app/mobile/tags/notifications.tag
index 59bcebaa4..9d665ec93 100644
--- a/src/web/app/mobile/tags/notifications.tag
+++ b/src/web/app/mobile/tags/notifications.tag
@@ -79,7 +79,7 @@
 		this.on('unmount', () => {
 			@stream.off 'notification' this.on-notification
 
-		on-notification(notification) {
+		this.on-notification = (notification) => {
 			@notifications.unshift notification
 			this.update();
 
diff --git a/src/web/app/mobile/tags/page/entrance.tag b/src/web/app/mobile/tags/page/entrance.tag
index 3ec43f0f6..1197d0578 100644
--- a/src/web/app/mobile/tags/page/entrance.tag
+++ b/src/web/app/mobile/tags/page/entrance.tag
@@ -45,15 +45,15 @@
 	<script>
 		this.mode = 'signin' 
 
-		signup() {
+		this.signup = () => {
 			this.mode = 'signup' 
 			this.update();
 
-		signin() {
+		this.signin = () => {
 			this.mode = 'signin' 
 			this.update();
 
-		introduction() {
+		this.introduction = () => {
 			this.mode = 'introduction' 
 			this.update();
 	</script>
diff --git a/src/web/app/mobile/tags/page/home.tag b/src/web/app/mobile/tags/page/home.tag
index cfa6d55da..d46e83474 100644
--- a/src/web/app/mobile/tags/page/home.tag
+++ b/src/web/app/mobile/tags/page/home.tag
@@ -23,21 +23,21 @@
 			this.Progress.start();
 
 			@stream.on 'post' this.on-stream-post
-			document.add-event-listener 'visibilitychange' @window-on-visibilitychange, false
+			document.addEventListener 'visibilitychange' @window-on-visibilitychange, false
 
 			this.refs.ui.refs.home.on('loaded', () => {
 				this.Progress.done();
 
 		this.on('unmount', () => {
 			@stream.off 'post' this.on-stream-post
-			document.remove-event-listener 'visibilitychange' @window-on-visibilitychange
+			document.removeEventListener 'visibilitychange' @window-on-visibilitychange
 
-		on-stream-post(post) {
+		this.on-stream-post = (post) => {
 			if document.hidden and post.user_id !== this.I.id
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
-		window-on-visibilitychange() {
+		this.window-on-visibilitychange = () => {
 			if !document.hidden
 				this.unread-count = 0
 				document.title = 'Misskey'
diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag
index 7d19a96d5..9319cfe68 100644
--- a/src/web/app/mobile/tags/post-detail.tag
+++ b/src/web/app/mobile/tags/post-detail.tag
@@ -391,18 +391,18 @@
 					this.replies = replies
 					this.update();
 
-		reply() {
+		this.reply = () => {
 			@open-post-form do
 				reply: @p
 
-		repost() {
+		this.repost = () => {
 			text = window.prompt '「' + @summary + '」をRepost'
 			if text?
 				this.api 'posts/create' do
 					repost_id: @p.id
 					text: if text == '' then undefined else text
 
-		like() {
+		this.like = () => {
 			if @p.is_liked
 				this.api 'posts/likes/delete' do
 					post_id: @p.id
@@ -416,7 +416,7 @@
 					@p.is_liked = true
 					this.update();
 
-		load-context() {
+		this.load-context = () => {
 			this.loading-context = true
 
 			// Get context
diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag
index 72778f3b4..7b7243cf0 100644
--- a/src/web/app/mobile/tags/post-form.tag
+++ b/src/web/app/mobile/tags/post-form.tag
@@ -200,13 +200,13 @@
 
 			this.refs.text.focus();
 
-		onkeypress(e) {
+		this.onkeypress = (e) => {
 			if (e.char-code == 10 || e.char-code == 13) && e.ctrlKey
 				@post!
 			else
 				return true
 
-		onpaste(e) {
+		this.onpaste = (e) => {
 			data = e.clipboardData
 			items = data.items
 			for i from 0 to items.length - 1
@@ -216,10 +216,10 @@
 						@upload item.getAsFile();
 			return true
 
-		select-file() {
+		this.select-file = () => {
 			this.refs.file.click!
 
-		select-file-from-drive() {
+		this.select-file-from-drive = () => {
 			browser = document.body.appendChild document.createElement 'mk-drive-selector' 
 			browser = riot.mount browser, do
 				multiple: true
@@ -227,16 +227,16 @@
 			browser.on('selected', (files) => {
 				files.for-each @add-file
 
-		change-file() {
+		this.change-file = () => {
 			files = this.refs.file.files
 			for i from 0 to files.length - 1
 				file = files.item i
 				@upload file
 
-		upload(file) {
+		this.upload = (file) => {
 			this.refs.uploader.upload file
 
-		add-file(file) {
+		this.add-file = (file) => {
 			file._remove = =>
 				this.files = this.files.filter (x) -> x.id != file.id
 				this.trigger 'change-files' this.files
@@ -246,14 +246,14 @@
 			this.trigger 'change-files' this.files
 			this.update();
 
-		add-poll() {
+		this.add-poll = () => {
 			this.poll = true
 
-		on-poll-destroyed() {
+		this.on-poll-destroyed = () => {
 			@update do
 				poll: false
 
-		post() {
+		this.post = () => {
 			this.wait = true
 
 			files = if this.files? and this.files.length > 0
@@ -274,11 +274,11 @@
 				this.wait = false
 				this.update();
 
-		cancel() {
+		this.cancel = () => {
 			this.trigger('cancel');
 			this.unmount();
 
-		cat() {
+		this.cat = () => {
 			this.refs.text.value = this.refs.text.value + get-cat!
 	</script>
 </mk-post-form>
diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag
index 120df4140..caa0af4be 100644
--- a/src/web/app/mobile/tags/search-posts.tag
+++ b/src/web/app/mobile/tags/search-posts.tag
@@ -22,7 +22,7 @@
 				res posts
 				this.trigger('loaded');
 
-		more() {
+		this.more = () => {
 			@offset += @max
 			this.api 'posts/search' do
 				query: @query
diff --git a/src/web/app/mobile/tags/timeline-post.tag b/src/web/app/mobile/tags/timeline-post.tag
index faa05ec7a..9cc6a088b 100644
--- a/src/web/app/mobile/tags/timeline-post.tag
+++ b/src/web/app/mobile/tags/timeline-post.tag
@@ -319,18 +319,18 @@
 						riot.mount @preview, do
 							url: t.content
 
-		reply() {
+		this.reply = () => {
 			@open-post-form do
 				reply: @p
 
-		repost() {
+		this.repost = () => {
 			text = window.prompt '「' + @summary + '」をRepost'
 			if text?
 				this.api 'posts/create' do
 					repost_id: @p.id
 					text: if text == '' then undefined else text
 
-		like() {
+		this.like = () => {
 			if @p.is_liked
 				this.api 'posts/likes/delete' do
 					post_id: @p.id
diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag
index 156c4e429..c6ae41455 100644
--- a/src/web/app/mobile/tags/timeline.tag
+++ b/src/web/app/mobile/tags/timeline.tag
@@ -91,7 +91,7 @@
 				post._date = date
 				post._datetext = month + '月 ' + date + '日'
 
-		more() {
+		this.more = () => {
 			if @init or @fetching or @posts.length == 0 then return
 			this.fetching = true
 			this.update();
@@ -99,20 +99,20 @@
 				this.fetching = false
 				@prepend-posts posts
 
-		set-posts(posts) {
+		this.set-posts = (posts) => {
 			this.posts = posts
 			this.update();
 
-		prepend-posts(posts) {
+		this.prepend-posts = (posts) => {
 			posts.for-each (post) =>
 				@posts.push post
 				this.update();
 
-		add-post(post) {
+		this.add-post = (post) => {
 			@posts.unshift post
 			this.update();
 
-		tail() {
+		this.tail = () => {
 			@posts[@posts.length - 1]
 	</script>
 </mk-timeline>
diff --git a/src/web/app/mobile/tags/ui-header.tag b/src/web/app/mobile/tags/ui-header.tag
index f4f44e972..6a7ec8ec5 100644
--- a/src/web/app/mobile/tags/ui-header.tag
+++ b/src/web/app/mobile/tags/ui-header.tag
@@ -98,7 +98,7 @@
 			if this.refs.title?
 				this.refs.title.innerHTML = title
 
-		post() {
+		this.post = () => {
 			@open-post-form!
 	</script>
 </mk-ui-header>
diff --git a/src/web/app/mobile/tags/ui-nav.tag b/src/web/app/mobile/tags/ui-nav.tag
index efdec8e14..67fbeefd1 100644
--- a/src/web/app/mobile/tags/ui-nav.tag
+++ b/src/web/app/mobile/tags/ui-nav.tag
@@ -123,7 +123,7 @@
 		this.on('mount', () => {
 			this.opts.ready!
 
-		search() {
+		this.search = () => {
 			query = window.prompt '検索' 
 			if query? and query != ''
 				@page '/search:' + query
diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag
index cb87469c0..3913de754 100644
--- a/src/web/app/mobile/tags/ui.tag
+++ b/src/web/app/mobile/tags/ui.tag
@@ -29,21 +29,21 @@
 		this.on('unmount', () => {
 			@stream.off 'notification' this.on-stream-notification
 
-		ready() {
+		this.ready = () => {
 			@ready-count++
 
 			if @ready-count == 2
 				@init-view-position!
 
-		init-view-position() {
+		this.init-view-position = () => {
 			top = this.refs.header.root.offset-height
 			this.refs.main.style.padding-top = top + 'px' 
 
-		toggle-drawer() {
+		this.toggle-drawer = () => {
 			this.is-drawer-opening = !@is-drawer-opening
 			this.refs.nav.root.style.display = if @is-drawer-opening then 'block' else 'none' 
 
-		on-stream-notification(notification) {
+		this.on-stream-notification = (notification) => {
 			el = document.body.appendChild document.createElement 'mk-notify' 
 			riot.mount el, do
 				notification: notification
diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag
index 49091421e..4eafb1ed9 100644
--- a/src/web/app/mobile/tags/user-followers.tag
+++ b/src/web/app/mobile/tags/user-followers.tag
@@ -10,7 +10,7 @@
 
 		this.user = this.opts.user
 
-		fetch(iknow, limit, cursor, cb) {
+		this.fetch = (iknow, limit, cursor, cb) => {
 			this.api 'users/followers' do
 				user_id: @user.id
 				iknow: iknow
diff --git a/src/web/app/mobile/tags/user-following.tag b/src/web/app/mobile/tags/user-following.tag
index c00894a4c..25d3c9926 100644
--- a/src/web/app/mobile/tags/user-following.tag
+++ b/src/web/app/mobile/tags/user-following.tag
@@ -10,7 +10,7 @@
 
 		this.user = this.opts.user
 
-		fetch(iknow, limit, cursor, cb) {
+		this.fetch = (iknow, limit, cursor, cb) => {
 			this.api 'users/following' do
 				user_id: @user.id
 				iknow: iknow
diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag
index a05fd8422..82a641354 100644
--- a/src/web/app/mobile/tags/user-timeline.tag
+++ b/src/web/app/mobile/tags/user-timeline.tag
@@ -22,7 +22,7 @@
 				res posts
 				this.trigger('loaded');
 
-		more() {
+		this.more = () => {
 			this.api 'users/posts' do
 				user_id: @user.id
 				with_media: @with-media
diff --git a/src/web/app/mobile/tags/user.tag b/src/web/app/mobile/tags/user.tag
index 6cd815a37..d36455e6e 100644
--- a/src/web/app/mobile/tags/user.tag
+++ b/src/web/app/mobile/tags/user.tag
@@ -172,19 +172,19 @@
 				this.trigger 'loaded' user
 				this.update();
 
-		go-posts() {
+		this.go-posts = () => {
 			this.page = 'posts' 
 			this.update();
 
-		go-media() {
+		this.go-media = () => {
 			this.page = 'media' 
 			this.update();
 
-		go-graphs() {
+		this.go-graphs = () => {
 			this.page = 'graphs' 
 			this.update();
 
-		go-likes() {
+		this.go-likes = () => {
 			this.page = 'likes' 
 			this.update();
 	</script>
diff --git a/src/web/app/mobile/tags/users-list.tag b/src/web/app/mobile/tags/users-list.tag
index 6d45c32c3..b0f7f73ff 100644
--- a/src/web/app/mobile/tags/users-list.tag
+++ b/src/web/app/mobile/tags/users-list.tag
@@ -82,7 +82,7 @@
 			@fetch =>
 				this.trigger('loaded');
 
-		fetch(cb) {
+		this.fetch = (cb) => {
 			this.fetching = true
 			this.update();
 			obj <~ this.opts.fetch do
@@ -95,7 +95,7 @@
 			this.update();
 			if cb? then cb!
 
-		more() {
+		this.more = () => {
 			this.more-fetching = true
 			this.update();
 			obj <~ this.opts.fetch do
@@ -107,7 +107,7 @@
 			this.more-fetching = false
 			this.update();
 
-		set-mode(mode) {
+		this.set-mode = (mode) => {
 			@update do
 				mode: mode
 

From a9dfe278f8021455fb67c87437ce120a4d67dc3f Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 10:44:44 +0900
Subject: [PATCH 05/32] wip

---
 package.json                                  |  2 --
 src/web/app/common/tags/messaging/form.tag    | 11 ++++----
 src/web/app/common/tags/messaging/index.tag   |  9 ++++--
 src/web/app/common/tags/messaging/message.tag | 28 +++++++++++--------
 webpack.config.ts                             |  2 +-
 5 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/package.json b/package.json
index 04335daa4..b90efb819 100644
--- a/package.json
+++ b/package.json
@@ -97,7 +97,6 @@
     "gulp-babel": "6.1.2",
     "gulp-cssnano": "2.1.2",
     "gulp-imagemin": "3.1.1",
-    "gulp-livescript": "3.0.1",
     "gulp-pug": "3.2.0",
     "gulp-rename": "1.2.2",
     "gulp-replace": "0.5.4",
@@ -109,7 +108,6 @@
     "is-root": "1.0.0",
     "is-url": "1.2.2",
     "js-yaml": "3.8.0",
-    "livescript": "1.5.0",
     "mime-types": "2.1.14",
     "mocha": "3.2.0",
     "mongodb": "2.2.24",
diff --git a/src/web/app/common/tags/messaging/form.tag b/src/web/app/common/tags/messaging/form.tag
index 8e74fbd35..4e5f5262a 100644
--- a/src/web/app/common/tags/messaging/form.tag
+++ b/src/web/app/common/tags/messaging/form.tag
@@ -128,17 +128,17 @@
 					this.upload(item.getAsFile());
 				}
 			}
-		}
+		};
 
 		this.onkeypress = (e) => {
 			if ((e.which == 10 || e.which == 13) && e.ctrlKey) {
 				this.send();
 			}
-		}
+		};
 
 		this.selectFile = () => {
 			this.refs.file.click();
-		}
+		};
 
 		this.selectFileFromDrive = () => {
 			const browser = document.body.appendChild(document.createElement('mk-select-file-from-drive-window'));
@@ -150,7 +150,7 @@
 			event.one('selected', files => {
 				files.forEach(this.addFile);
 			});
-		}
+		};
 
 		this.send = () => {
 			this.sending = true;
@@ -165,11 +165,12 @@
 				this.sending = false;
 				this.update();
 			});
+		};
 
 		this.clear = () => {
 			this.refs.text.value = '';
 			this.files = [];
 			this.update();
-		}
+		};
 	</script>
 </mk-messaging-form>
diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
index e7d110140..74173b738 100644
--- a/src/web/app/common/tags/messaging/index.tag
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -303,7 +303,7 @@
 				this.history = history;
 				this.update();
 			});
-		}
+		});
 
 		this.search = () => {
 			const q = this.refs.search.value;
@@ -322,14 +322,16 @@
 					this.update();
 				.catch (err) =>
 					console.error err
+		};
 
-		this.on-search-keydown = (e) => {
-			key = e.which
+		this.on-search-keydown = e => {
+			const key = e.which;
 			switch (key)
 				| 9, 40 => // Key[TAB] or Key[↓]
 					e.preventDefault();
 					e.stopPropagation();
 					this.refs.search-result.childNodes[0].focus();
+		};
 
 		this.on-search-result-keydown = (i, e) => {
 			key = e.which
@@ -350,6 +352,7 @@
 					e.preventDefault();
 					e.stopPropagation();
 					(this.refs.search-result.childNodes[i].next-element-sibling || this.refs.search-result.childNodes[0]).focus();
+		};
 
 	</script>
 </mk-messaging>
diff --git a/src/web/app/common/tags/messaging/message.tag b/src/web/app/common/tags/messaging/message.tag
index 96b4e8daf..de763c779 100644
--- a/src/web/app/common/tags/messaging/message.tag
+++ b/src/web/app/common/tags/messaging/message.tag
@@ -206,25 +206,29 @@
 		this.mixin('i');
 		this.mixin('text');
 
-		this.message = this.opts.message
-		@message.is_me = @message.user.id == this.I.id
+		this.message = this.opts.message;
+		this.message.is_me = this.message.user.id == this.I.id;
 
 		this.on('mount', () => {
-			if @message.text?
-				tokens = @analyze @message.text
+			if (this.message.text) {
+				const tokens = this.analyze(this.message.text);
 
-				this.refs.text.innerHTML = @compile tokens
+				this.refs.text.innerHTML = this.compile(tokens);
 
-				this.refs.text.children.for-each (e) =>
-					if e.tag-name == 'MK-URL' 
-						riot.mount e
+				this.refs.text.children.forEach(e => {
+					if (e.tagName == 'MK-URL') riot.mount(e);
+				});
 
 				// URLをプレビュー
 				tokens
-					.filter (t) -> t.type == 'link' 
-					.map (t) =>
-						this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-						riot.mount @preview, do
+					.filter(t => t.type == 'link')
+					.map(t => {
+						const el = this.refs.text.appendChild(document.createElement('mk-url-preview'));
+						riot.mount(el, {
 							url: t.content
+						});
+					});
+			}
+		});
 	</script>
 </mk-messaging-message>
diff --git a/webpack.config.ts b/webpack.config.ts
index 195c433a9..6928536ff 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -31,7 +31,7 @@ module.exports = (config, commit, env) => {
 					loader: 'riot-tag-loader',
 					query: {
 						hot: false,
-						type: 'livescript',
+						type: 'es6',
 						style: 'stylus',
 						expr: false,
 						compact: true,

From d042aa4fcb52200f2211acecd8ac03750e92c108 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 11:02:43 +0900
Subject: [PATCH 06/32] wip

---
 src/web/app/common/tags/messaging/index.tag   | 16 ++---
 src/web/app/common/tags/messaging/room.tag    | 10 +--
 src/web/app/common/tags/ripple-string.tag     |  2 +-
 src/web/app/common/tags/signin-history.tag    |  4 +-
 src/web/app/common/tags/signin.tag            |  2 +-
 src/web/app/common/tags/signup.tag            | 10 +--
 src/web/app/common/tags/time.tag              | 24 +++----
 src/web/app/desktop/tags/analog-clock.tag     | 10 +--
 .../desktop/tags/autocomplete-suggestion.tag  |  6 +-
 .../app/desktop/tags/big-follow-button.tag    |  8 +--
 src/web/app/desktop/tags/contextmenu.tag      |  4 +-
 src/web/app/desktop/tags/dialog.tag           |  4 +-
 src/web/app/desktop/tags/drive/browser.tag    | 72 +++++++++----------
 src/web/app/desktop/tags/drive/file.tag       | 10 +--
 src/web/app/desktop/tags/drive/folder.tag     | 12 ++--
 src/web/app/desktop/tags/drive/nav-folder.tag |  4 +-
 src/web/app/desktop/tags/follow-button.tag    |  8 +--
 .../app/desktop/tags/following-setuper.tag    |  4 +-
 .../desktop/tags/home-widgets/calendar.tag    | 12 ++--
 .../desktop/tags/home-widgets/mentions.tag    |  4 +-
 .../tags/home-widgets/photo-stream.tag        |  4 +-
 .../desktop/tags/home-widgets/rss-reader.tag  |  4 +-
 .../desktop/tags/home-widgets/timeline.tag    | 12 ++--
 .../app/desktop/tags/home-widgets/tips.tag    |  4 +-
 .../tags/home-widgets/user-recommendation.tag |  8 +--
 src/web/app/desktop/tags/home.tag             |  6 +-
 src/web/app/desktop/tags/notifications.tag    | 10 +--
 src/web/app/desktop/tags/pages/home.tag       |  4 +-
 src/web/app/desktop/tags/post-detail-sub.tag  | 20 +++---
 src/web/app/desktop/tags/post-detail.tag      | 36 +++++-----
 src/web/app/desktop/tags/post-form.tag        | 12 ++--
 src/web/app/desktop/tags/post-preview.tag     |  2 +-
 .../app/desktop/tags/post-status-graph.tag    |  8 +--
 src/web/app/desktop/tags/search-posts.tag     |  6 +-
 src/web/app/desktop/tags/stream-indicator.tag |  4 +-
 src/web/app/desktop/tags/sub-post-content.tag |  6 +-
 .../app/desktop/tags/timeline-post-sub.tag    |  2 +-
 src/web/app/desktop/tags/timeline-post.tag    | 40 +++++------
 src/web/app/desktop/tags/timeline.tag         | 14 ++--
 .../app/desktop/tags/ui-header-account.tag    |  4 +-
 src/web/app/desktop/tags/ui-header-clock.tag  | 16 ++---
 src/web/app/desktop/tags/ui-header-nav.tag    |  8 +--
 .../desktop/tags/ui-header-notifications.tag  |  4 +-
 src/web/app/desktop/tags/ui-header-search.tag |  2 +-
 src/web/app/desktop/tags/user-photos.tag      |  4 +-
 src/web/app/desktop/tags/user-timeline.tag    |  4 +-
 src/web/app/desktop/tags/users-list.tag       |  4 +-
 src/web/app/desktop/tags/window.tag           |  2 +-
 src/web/app/dev/tags/new-app-form.tag         |  2 +-
 src/web/app/mobile/tags/drive.tag             | 32 ++++-----
 src/web/app/mobile/tags/follow-button.tag     |  8 +--
 src/web/app/mobile/tags/home-timeline.tag     | 12 ++--
 src/web/app/mobile/tags/notifications.tag     | 10 +--
 src/web/app/mobile/tags/page/home.tag         |  4 +-
 src/web/app/mobile/tags/page/messaging.tag    |  2 +-
 src/web/app/mobile/tags/post-detail.tag       | 36 +++++-----
 src/web/app/mobile/tags/post-form.tag         |  8 +--
 src/web/app/mobile/tags/stream-indicator.tag  |  4 +-
 src/web/app/mobile/tags/sub-post-content.tag  |  6 +-
 src/web/app/mobile/tags/timeline-post.tag     | 36 +++++-----
 src/web/app/mobile/tags/timeline.tag          | 18 ++---
 src/web/app/mobile/tags/ui-nav.tag            |  2 +-
 src/web/app/mobile/tags/ui.tag                |  4 +-
 src/web/app/mobile/tags/users-list.tag        |  4 +-
 64 files changed, 332 insertions(+), 332 deletions(-)

diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
index 74173b738..ca1adaaa7 100644
--- a/src/web/app/common/tags/messaging/index.tag
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -314,11 +314,11 @@
 					query: q
 					max: 5
 				.then (users) =>
-					users.for-each (user) =>
+					users.forEach (user) =>
 						user._click = =>
 							this.trigger 'navigate-user' user
-							this.search-result = []
-					this.search-result = users
+							this.searchResult = []
+					this.searchResult = users
 					this.update();
 				.catch (err) =>
 					console.error err
@@ -330,16 +330,16 @@
 				| 9, 40 => // Key[TAB] or Key[↓]
 					e.preventDefault();
 					e.stopPropagation();
-					this.refs.search-result.childNodes[0].focus();
+					this.refs.searchResult.childNodes[0].focus();
 		};
 
-		this.on-search-result-keydown = (i, e) => {
+		this.on-searchResult-keydown = (i, e) => {
 			key = e.which
 			switch (key)
 				| 10, 13 => // Key[ENTER]
 					e.preventDefault();
 					e.stopPropagation();
-					@search-result[i]._click!
+					this.searchResult[i]._click();
 				| 27 => // Key[ESC]
 					e.preventDefault();
 					e.stopPropagation();
@@ -347,11 +347,11 @@
 				| 38 => // Key[↑]
 					e.preventDefault();
 					e.stopPropagation();
-					(this.refs.search-result.childNodes[i].previous-element-sibling || this.refs.search-result.childNodes[@search-result.length - 1]).focus();
+					(this.refs.searchResult.childNodes[i].previousElementSibling || this.refs.searchResult.childNodes[this.searchResult.length - 1]).focus();
 				| 9, 40 => // Key[TAB] or Key[↓]
 					e.preventDefault();
 					e.stopPropagation();
-					(this.refs.search-result.childNodes[i].next-element-sibling || this.refs.search-result.childNodes[0]).focus();
+					(this.refs.searchResult.childNodes[i].nextElementSibling || this.refs.searchResult.childNodes[0]).focus();
 		};
 
 	</script>
diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index f04fd4638..6565d4c41 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -159,9 +159,9 @@
 			document.removeEventListener 'visibilitychange' this.on-visibilitychange
 
 		this.on('update', () => {
-			@messages.for-each (message) =>
-				date = (new Date message.created_at).get-date!
-				month = (new Date message.created_at).get-month! + 1
+			@messages.forEach (message) =>
+				date = (new Date message.created_at).getDate()
+				month = (new Date message.created_at).getMonth() + 1
 				message._date = date
 				message._datetext = month + '月 ' + date + '日'
 
@@ -184,7 +184,7 @@
 
 		this.on-read = (ids) => {
 			if not Array.isArray ids then ids = [ids]
-			ids.for-each (id) =>
+			ids.forEach (id) =>
 				if (@messages.some (x) => x.id == id)
 					exist = (@messages.map (x) -> x.id).index-of id
 					@messages[exist].is_read = true
@@ -215,7 +215,7 @@
 
 		this.on-visibilitychange = () => {
 			if document.hidden then return
-			@messages.for-each (message) =>
+			@messages.forEach (message) =>
 				if message.user_id != this.I.id and not message.is_read
 					@connection.socket.send JSON.stringify do
 						type: 'read' 
diff --git a/src/web/app/common/tags/ripple-string.tag b/src/web/app/common/tags/ripple-string.tag
index f52d75e70..f6cd8c94d 100644
--- a/src/web/app/common/tags/ripple-string.tag
+++ b/src/web/app/common/tags/ripple-string.tag
@@ -17,7 +17,7 @@
 		this.on('mount', () => {
 			text = this.root.innerHTML
 			this.root.innerHTML = ''
-			(text.split '').for-each (c, i) =>
+			(text.split '').forEach (c, i) =>
 				ce = document.createElement 'span' 
 				ce.innerHTML = c
 				ce.style.animationDelay = (i / 10) + 's'
diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag
index 97087e347..6b2ca1e6c 100644
--- a/src/web/app/common/tags/signin-history.tag
+++ b/src/web/app/common/tags/signin-history.tag
@@ -63,10 +63,10 @@
 			.catch (err) =>
 				console.error err
 
-			@stream.on 'signin' this.on-signin
+			this.stream.on 'signin' this.on-signin
 
 		this.on('unmount', () => {
-			@stream.off 'signin' this.on-signin
+			this.stream.off 'signin' this.on-signin
 
 		this.on-signin = (signin) => {
 			@history.unshift signin
diff --git a/src/web/app/common/tags/signin.tag b/src/web/app/common/tags/signin.tag
index e71795708..204ed8326 100644
--- a/src/web/app/common/tags/signin.tag
+++ b/src/web/app/common/tags/signin.tag
@@ -127,7 +127,7 @@
 				username: this.refs.username.value
 				password: this.refs.password.value
 			.then =>
-				location.reload!
+				location.reload();
 			.catch =>
 				alert 'something happened'
 				this.signing = false
diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag
index f8ac1c19c..06e044a41 100644
--- a/src/web/app/common/tags/signup.tag
+++ b/src/web/app/common/tags/signup.tag
@@ -268,15 +268,15 @@
 		this.onsubmit = (e) => {
 			e.preventDefault();
 
-			username = this.refs.username.value
-			password = this.refs.password.value
+			const username = this.refs.username.value;
+			const password = this.refs.password.value;
 
 			locker = document.body.appendChild document.createElement 'mk-locker' 
 
 			this.api 'signup' do
-				username: username
-				password: password
-				'g-recaptcha-response': grecaptcha.get-response!
+				username: username,
+				password: password,
+				'g-recaptcha-response': grecaptcha.getResponse()
 			.then =>
 				this.api 'signin' do
 					username: username
diff --git a/src/web/app/common/tags/time.tag b/src/web/app/common/tags/time.tag
index 131113353..1bf078916 100644
--- a/src/web/app/common/tags/time.tag
+++ b/src/web/app/common/tags/time.tag
@@ -6,25 +6,25 @@
 		this.tickid = null
 
 		this.absolute = 
-			@time.get-full-year! + '年' +
-			@time.get-month! + 1 + '月' +
-			@time.get-date!      + '日' +
+			this.time.getFullYear() + '年' +
+			this.time.getMonth() + 1 + '月' +
+			this.time.getDate()      + '日' +
 			' ' +
-			@time.get-hours!     + '時' +
-			@time.get-minutes!   + '分' 
+			this.time.getHours()     + '時' +
+			this.time.getMinutes()   + '分' 
 
 		this.on('mount', () => {
-			if @mode == 'relative' or @mode == 'detail' 
-				@tick!
-				this.tickid = set-interval @tick, 1000ms
+			if this.mode == 'relative' or this.mode == 'detail' 
+				this.tick!
+				this.tickid = setInterval this.tick, 1000ms
 
 		this.on('unmount', () => {
-			if @mode == 'relative' or @mode == 'detail' 
-				clear-interval @tickid
+			if this.mode == 'relative' or this.mode == 'detail' 
+				clearInterval this.tickid
 
 		this.tick = () => {
-			now = new Date!
-			ago = (now - @time) / 1000ms
+			const now = new Date();
+			ago = (now - this.time) / 1000ms
 			this.relative = switch
 				| ago >= 31536000s => ~~(ago / 31536000s) + '年前'
 				| ago >= 2592000s  => ~~(ago / 2592000s)  + 'ヶ月前'
diff --git a/src/web/app/desktop/tags/analog-clock.tag b/src/web/app/desktop/tags/analog-clock.tag
index c1390be64..ec627ec65 100644
--- a/src/web/app/desktop/tags/analog-clock.tag
+++ b/src/web/app/desktop/tags/analog-clock.tag
@@ -11,16 +11,16 @@
 	<script>
 		this.on('mount', () => {
 			@draw!
-			this.clock = set-interval @draw, 1000ms
+			this.clock = setInterval @draw, 1000ms
 
 		this.on('unmount', () => {
-			clear-interval @clock
+			clearInterval @clock
 
 		this.draw = () => {
-			now = new Date!
+			const now = new Date();
 			s = now.get-seconds!
-			m = now.get-minutes!
-			h = now.get-hours!
+			m = now.getMinutes()
+			h = now.getHours()
 
 			vec2 = (x, y) ->
 				this.x = x
diff --git a/src/web/app/desktop/tags/autocomplete-suggestion.tag b/src/web/app/desktop/tags/autocomplete-suggestion.tag
index 29ce938b8..126c3f3be 100644
--- a/src/web/app/desktop/tags/autocomplete-suggestion.tag
+++ b/src/web/app/desktop/tags/autocomplete-suggestion.tag
@@ -92,7 +92,7 @@
 			@textarea.addEventListener 'keydown' this.on-keydown
 
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) =>
+			Array.prototype.forEach.call all, (el) =>
 				el.addEventListener 'mousedown' @mousedown
 
 			this.api 'users/search_by_username' do
@@ -109,7 +109,7 @@
 			@textarea.removeEventListener 'keydown' this.on-keydown
 
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) =>
+			Array.prototype.forEach.call all, (el) =>
 				el.removeEventListener 'mousedown' @mousedown
 
 		this.mousedown = (e) => {
@@ -164,7 +164,7 @@
 			@apply-select!
 
 		this.apply-select = () => {
-			this.refs.users.children.for-each (el) =>
+			this.refs.users.children.forEach (el) =>
 				el.remove-attribute 'data-selected' 
 
 			this.refs.users.children[@select].setAttribute 'data-selected' \true
diff --git a/src/web/app/desktop/tags/big-follow-button.tag b/src/web/app/desktop/tags/big-follow-button.tag
index 78ecbc2d6..e4200277c 100644
--- a/src/web/app/desktop/tags/big-follow-button.tag
+++ b/src/web/app/desktop/tags/big-follow-button.tag
@@ -84,12 +84,12 @@
 				this.user = user
 				this.init = false
 				this.update();
-				@stream.on 'follow' this.on-stream-follow
-				@stream.on 'unfollow' this.on-stream-unfollow
+				this.stream.on 'follow' this.on-stream-follow
+				this.stream.on 'unfollow' this.on-stream-unfollow
 
 		this.on('unmount', () => {
-			@stream.off 'follow' this.on-stream-follow
-			@stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off 'follow' this.on-stream-follow
+			this.stream.off 'unfollow' this.on-stream-unfollow
 
 		this.on-stream-follow = (user) => {
 			if user.id == @user.id
diff --git a/src/web/app/desktop/tags/contextmenu.tag b/src/web/app/desktop/tags/contextmenu.tag
index 400090c6c..87dde8a84 100644
--- a/src/web/app/desktop/tags/contextmenu.tag
+++ b/src/web/app/desktop/tags/contextmenu.tag
@@ -105,7 +105,7 @@
 
 		this.open = (pos) => {
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) =>
+			Array.prototype.forEach.call all, (el) =>
 				el.addEventListener 'mousedown' @mousedown
 			this.root.style.display = 'block' 
 			this.root.style.left = pos.x + 'px' 
@@ -123,7 +123,7 @@
 
 		this.close = () => {
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) =>
+			Array.prototype.forEach.call all, (el) =>
 				el.removeEventListener 'mousedown' @mousedown
 			this.trigger('closed');
 			this.unmount();
diff --git a/src/web/app/desktop/tags/dialog.tag b/src/web/app/desktop/tags/dialog.tag
index f163f99b8..d4088fabd 100644
--- a/src/web/app/desktop/tags/dialog.tag
+++ b/src/web/app/desktop/tags/dialog.tag
@@ -80,10 +80,10 @@
 	</style>
 	<script>
 		this.can-through = if opts.can-through? then opts.can-through else true
-		this.opts.buttons.for-each (button) =>
+		this.opts.buttons.forEach (button) =>
 			button._onclick = =>
 				if button.onclick?
-					button.onclick!
+					button.onclick();
 				@close!
 
 		this.on('mount', () => {
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index 383da9018..c13832523 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -243,24 +243,24 @@
 		this.mixin('input-dialog');
 		this.mixin('stream');
 
-		this.files = []
-		this.folders = []
-		this.hierarchy-folders = []
+		this.files = [];
+		this.folders = [];
+		this.hierarchyFolders = [];
 
-		this.uploads = []
+		this.uploads = [];
 
 		// 現在の階層(フォルダ)
 		// * null でルートを表す
-		this.folder = null
+		this.folder = null;
 
 		this.multiple = if this.opts.multiple? then this.opts.multiple else false
 
 		// ドロップされようとしているか
-		this.draghover = false
+		this.draghover = false;
 
 		// 自信の所有するアイテムがドラッグをスタートさせたか
 		// (自分自身の階層にドロップできないようにするためのフラグ)
-		this.is-drag-source = false
+		this.is-drag-source = false;
 
 		this.on('mount', () => {
 			this.refs.uploader.on('uploaded', (file) => {
@@ -270,10 +270,10 @@
 				this.uploads = uploads
 				this.update();
 
-			@stream.on 'drive_file_created' this.on-stream-drive-file-created
-			@stream.on 'drive_file_updated' this.on-stream-drive-file-updated
-			@stream.on 'drive_folder_created' this.on-stream-drive-folder-created
-			@stream.on 'drive_folder_updated' this.on-stream-drive-folder-updated
+			this.stream.on 'drive_file_created' this.on-stream-drive-file-created
+			this.stream.on 'drive_file_updated' this.on-stream-drive-file-updated
+			this.stream.on 'drive_folder_created' this.on-stream-drive-folder-created
+			this.stream.on 'drive_folder_updated' this.on-stream-drive-folder-updated
 
 			// Riotのバグでnullを渡しても""になる
 			// https://github.com/riot/riot/issues/2080
@@ -284,10 +284,10 @@
 				@load!
 
 		this.on('unmount', () => {
-			@stream.off 'drive_file_created' this.on-stream-drive-file-created
-			@stream.off 'drive_file_updated' this.on-stream-drive-file-updated
-			@stream.off 'drive_folder_created' this.on-stream-drive-folder-created
-			@stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
+			this.stream.off 'drive_file_created' this.on-stream-drive-file-created
+			this.stream.off 'drive_file_updated' this.on-stream-drive-file-updated
+			this.stream.off 'drive_folder_created' this.on-stream-drive-folder-created
+			this.stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
 
 		this.on-stream-drive-file-created = (file) => {
 			@add-file file, true
@@ -315,30 +315,30 @@
 
 			rect = this.refs.main.get-bounding-client-rect!
 
-			left = e.page-x + this.refs.main.scroll-left - rect.left - window.page-x-offset
-			top = e.page-y + this.refs.main.scroll-top - rect.top - window.page-y-offset
+			left = e.pageX + this.refs.main.scroll-left - rect.left - window.pageXOffset
+			top = e.pageY + this.refs.main.scroll-top - rect.top - window.pageYOffset
 
 			move = (e) =>
 				this.refs.selection.style.display = 'block' 
 
-				cursor-x = e.page-x + this.refs.main.scroll-left - rect.left - window.page-x-offset
-				cursor-y = e.page-y + this.refs.main.scroll-top - rect.top - window.page-y-offset
-				w = cursor-x - left
-				h = cursor-y - top
+				cursorX = e.pageX + this.refs.main.scroll-left - rect.left - window.pageXOffset
+				cursorY = e.pageY + this.refs.main.scroll-top - rect.top - window.pageYOffset
+				w = cursorX - left
+				h = cursorY - top
 
 				if w > 0
 					this.refs.selection.style.width = w + 'px' 
 					this.refs.selection.style.left = left + 'px' 
 				else
 					this.refs.selection.style.width = -w + 'px' 
-					this.refs.selection.style.left = cursor-x + 'px' 
+					this.refs.selection.style.left = cursorX + 'px' 
 
 				if h > 0
 					this.refs.selection.style.height = h + 'px' 
 					this.refs.selection.style.top = top + 'px' 
 				else
 					this.refs.selection.style.height = -h + 'px' 
-					this.refs.selection.style.top = cursor-y + 'px' 
+					this.refs.selection.style.top = cursorY + 'px' 
 
 			up = (e) =>
 				document.document-element.removeEventListener 'mousemove' move
@@ -351,7 +351,7 @@
 
 		this.path-oncontextmenu = (e) => {
 			e.preventDefault();
-			e.stop-immediate-propagation!
+			e.stopImmediatePropagation();
 			return false
 
 		this.ondragover = (e) => {
@@ -361,7 +361,7 @@
 			// ドラッグ元が自分自身の所有するアイテムかどうか
 			if !@is-drag-source
 				// ドラッグされてきたものがファイルだったら
-				if e.dataTransfer.effect-allowed == 'all' 
+				if e.dataTransfer.effectAllowed == 'all' 
 					e.dataTransfer.dropEffect = 'copy' 
 				else
 					e.dataTransfer.dropEffect = 'move' 
@@ -387,7 +387,7 @@
 
 			// ドロップされてきたものがファイルだったら
 			if e.dataTransfer.files.length > 0
-				Array.prototype.for-each.call e.dataTransfer.files, (file) =>
+				Array.prototype.forEach.call e.dataTransfer.files, (file) =>
 					@upload file, this.folder
 				return false
 
@@ -440,20 +440,20 @@
 
 		this.oncontextmenu = (e) => {
 			e.preventDefault();
-			e.stop-immediate-propagation!
+			e.stopImmediatePropagation();
 
 			ctx = document.body.appendChild document.createElement 'mk-drive-browser-base-contextmenu' 
 			ctx = riot.mount ctx, do
-				browser: @
+				browser: this
 			ctx = ctx.0
 			ctx.open do
-				x: e.page-x - window.page-x-offset
-				y: e.page-y - window.page-y-offset
+				x: e.pageX - window.pageXOffset
+				y: e.pageY - window.pageYOffset
 
 			return false
 
 		this.select-local-file = () => {
-			this.refs.file-input.click!
+			this.refs.file-input.click();
 
 		this.url-upload = () => {
 			url <~ @input-dialog do
@@ -522,10 +522,10 @@
 				folder_id: target-folder
 			.then (folder) =>
 				this.folder = folder
-				this.hierarchy-folders = []
+				this.hierarchyFolders = []
 
 				x = (f) =>
-					@hierarchy-folders.unshift f
+					@hierarchyFolders.unshift f
 					if f.parent?
 						x f.parent
 
@@ -588,7 +588,7 @@
 		this.go-root = () => {
 			if this.folder != null
 				this.folder = null
-				this.hierarchy-folders = []
+				this.hierarchyFolders = []
 				this.update();
 				@load!
 
@@ -635,9 +635,9 @@
 			flag = false
 			complete = =>
 				if flag
-					load-folders.for-each (folder) =>
+					load-folders.forEach (folder) =>
 						@add-folder folder
-					load-files.for-each (file) =>
+					load-files.forEach (file) =>
 						@add-file file
 					this.loading = false
 					this.update();
diff --git a/src/web/app/desktop/tags/drive/file.tag b/src/web/app/desktop/tags/drive/file.tag
index e0e9beb21..7016f7429 100644
--- a/src/web/app/desktop/tags/drive/file.tag
+++ b/src/web/app/desktop/tags/drive/file.tag
@@ -166,14 +166,14 @@
 				if this.file._selected
 					this.browser.trigger 'selected' this.file
 				else
-					this.browser.files.for-each (file) =>
+					this.browser.files.forEach (file) =>
 						file._selected = false
 					this.file._selected = true
 					this.browser.trigger 'change-selection' this.file
 
 		this.oncontextmenu = (e) => {
 			e.preventDefault();
-			e.stop-immediate-propagation!
+			e.stopImmediatePropagation();
 
 			this.is-contextmenu-showing = true
 			this.update();
@@ -183,15 +183,15 @@
 				file: this.file
 			ctx = ctx.0
 			ctx.open do
-				x: e.page-x - window.page-x-offset
-				y: e.page-y - window.page-y-offset
+				x: e.pageX - window.pageXOffset
+				y: e.pageY - window.pageYOffset
 			ctx.on('closed', () => {
 				this.is-contextmenu-showing = false
 				this.update();
 			return false
 
 		this.ondragstart = (e) => {
-			e.dataTransfer.effect-allowed = 'move' 
+			e.dataTransfer.effectAllowed = 'move' 
 			e.dataTransfer.set-data 'text' JSON.stringify do
 				type: 'file' 
 				id: this.file.id
diff --git a/src/web/app/desktop/tags/drive/folder.tag b/src/web/app/desktop/tags/drive/folder.tag
index 25524a80d..02215dac3 100644
--- a/src/web/app/desktop/tags/drive/folder.tag
+++ b/src/web/app/desktop/tags/drive/folder.tag
@@ -77,7 +77,7 @@
 			// 自分自身がドラッグされていない場合
 			if !@is-dragging
 				// ドラッグされてきたものがファイルだったら
-				if e.dataTransfer.effect-allowed == 'all' 
+				if e.dataTransfer.effectAllowed == 'all' 
 					e.dataTransfer.dropEffect = 'copy' 
 				else
 					e.dataTransfer.dropEffect = 'move' 
@@ -99,7 +99,7 @@
 
 			// ファイルだったら
 			if e.dataTransfer.files.length > 0
-				Array.prototype.for-each.call e.dataTransfer.files, (file) =>
+				Array.prototype.forEach.call e.dataTransfer.files, (file) =>
 					this.browser.upload file, this.folder
 				return false
 
@@ -147,7 +147,7 @@
 			return false
 
 		this.ondragstart = (e) => {
-			e.dataTransfer.effect-allowed = 'move' 
+			e.dataTransfer.effectAllowed = 'move' 
 			e.dataTransfer.set-data 'text' JSON.stringify do
 				type: 'folder' 
 				id: this.folder.id
@@ -163,7 +163,7 @@
 
 		this.oncontextmenu = (e) => {
 			e.preventDefault();
-			e.stop-immediate-propagation!
+			e.stopImmediatePropagation();
 
 			this.is-contextmenu-showing = true
 			this.update();
@@ -173,8 +173,8 @@
 				folder: this.folder
 			ctx = ctx.0
 			ctx.open do
-				x: e.page-x - window.page-x-offset
-				y: e.page-y - window.page-y-offset
+				x: e.pageX - window.pageXOffset
+				y: e.pageY - window.pageYOffset
 			ctx.on('closed', () => {
 				this.is-contextmenu-showing = false
 				this.update();
diff --git a/src/web/app/desktop/tags/drive/nav-folder.tag b/src/web/app/desktop/tags/drive/nav-folder.tag
index 5a620d76c..f0dab487e 100644
--- a/src/web/app/desktop/tags/drive/nav-folder.tag
+++ b/src/web/app/desktop/tags/drive/nav-folder.tag
@@ -33,7 +33,7 @@
 			if this.folder == null and this.browser.folder == null
 				e.dataTransfer.dropEffect = 'none' 
 			// ドラッグされてきたものがファイルだったら
-			else if e.dataTransfer.effect-allowed == 'all' 
+			else if e.dataTransfer.effectAllowed == 'all' 
 				e.dataTransfer.dropEffect = 'copy' 
 			else
 				e.dataTransfer.dropEffect = 'move' 
@@ -53,7 +53,7 @@
 
 			// ファイルだったら
 			if e.dataTransfer.files.length > 0
-				Array.prototype.for-each.call e.dataTransfer.files, (file) =>
+				Array.prototype.forEach.call e.dataTransfer.files, (file) =>
 					this.browser.upload file, this.folder
 				return false
 
diff --git a/src/web/app/desktop/tags/follow-button.tag b/src/web/app/desktop/tags/follow-button.tag
index 87284cbc0..7b4f8f81d 100644
--- a/src/web/app/desktop/tags/follow-button.tag
+++ b/src/web/app/desktop/tags/follow-button.tag
@@ -81,12 +81,12 @@
 				this.user = user
 				this.init = false
 				this.update();
-				@stream.on 'follow' this.on-stream-follow
-				@stream.on 'unfollow' this.on-stream-unfollow
+				this.stream.on 'follow' this.on-stream-follow
+				this.stream.on 'unfollow' this.on-stream-unfollow
 
 		this.on('unmount', () => {
-			@stream.off 'follow' this.on-stream-follow
-			@stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off 'follow' this.on-stream-follow
+			this.stream.off 'unfollow' this.on-stream-unfollow
 
 		this.on-stream-follow = (user) => {
 			if user.id == @user.id
diff --git a/src/web/app/desktop/tags/following-setuper.tag b/src/web/app/desktop/tags/following-setuper.tag
index fd1aa4bc8..fa540511a 100644
--- a/src/web/app/desktop/tags/following-setuper.tag
+++ b/src/web/app/desktop/tags/following-setuper.tag
@@ -142,7 +142,7 @@
 
 			this.api 'users/recommendation' do
 				limit: @limit
-				offset: @limit * @page
+				offset: @limit * this.page
 			.then (users) =>
 				this.loading = false
 				this.users = users
@@ -154,7 +154,7 @@
 			if @users.length < @limit
 				this.page = 0
 			else
-				@page++
+				this.page++
 			@load!
 
 		this.close = () => {
diff --git a/src/web/app/desktop/tags/home-widgets/calendar.tag b/src/web/app/desktop/tags/home-widgets/calendar.tag
index fb8d88962..acf8e8c73 100644
--- a/src/web/app/desktop/tags/home-widgets/calendar.tag
+++ b/src/web/app/desktop/tags/home-widgets/calendar.tag
@@ -107,10 +107,10 @@
 	</style>
 	<script>
 		this.draw = () => {
-			now = new Date!
-			nd = now.get-date!
-			nm = now.get-month!
-			ny = now.get-full-year!
+			const now = new Date();
+			nd = now.getDate()
+			nm = now.getMonth()
+			ny = now.getFullYear()
 
 			this.year = ny
 			this.month = nm + 1
@@ -140,9 +140,9 @@
 		@draw!
 
 		this.on('mount', () => {
-			this.clock = set-interval @draw, 1000ms
+			this.clock = setInterval @draw, 1000ms
 
 		this.on('unmount', () => {
-			clear-interval @clock
+			clearInterval @clock
 	</script>
 </mk-calendar-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/mentions.tag b/src/web/app/desktop/tags/home-widgets/mentions.tag
index 492eacb17..706242547 100644
--- a/src/web/app/desktop/tags/home-widgets/mentions.tag
+++ b/src/web/app/desktop/tags/home-widgets/mentions.tag
@@ -73,7 +73,7 @@
 
 		this.fetch = (cb) => {
 			this.api 'posts/mentions' do
-				following: @mode == 'following' 
+				following: this.mode == 'following' 
 			.then (posts) =>
 				this.is-loading = false
 				this.is-empty = posts.length == 0
@@ -90,7 +90,7 @@
 			this.more-loading = true
 			this.update();
 			this.api 'posts/mentions' do
-				following: @mode == 'following' 
+				following: this.mode == 'following' 
 				max_id: this.refs.timeline.tail!.id
 			.then (posts) =>
 				this.more-loading = false
diff --git a/src/web/app/desktop/tags/home-widgets/photo-stream.tag b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
index f7a80f40a..c606fac64 100644
--- a/src/web/app/desktop/tags/home-widgets/photo-stream.tag
+++ b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
@@ -64,7 +64,7 @@
 		this.initializing = true
 
 		this.on('mount', () => {
-			@stream.on 'drive_file_created' this.on-stream-drive-file-created
+			this.stream.on 'drive_file_created' this.on-stream-drive-file-created
 
 			this.api 'drive/stream' do
 				type: 'image/*'
@@ -75,7 +75,7 @@
 				this.update();
 
 		this.on('unmount', () => {
-			@stream.off 'drive_file_created' this.on-stream-drive-file-created
+			this.stream.off 'drive_file_created' this.on-stream-drive-file-created
 
 		this.on-stream-drive-file-created = (file) => {
 			if /^image\/.+$/.test file.type
diff --git a/src/web/app/desktop/tags/home-widgets/rss-reader.tag b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
index 2ced342a4..d44f76b16 100644
--- a/src/web/app/desktop/tags/home-widgets/rss-reader.tag
+++ b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
@@ -73,10 +73,10 @@
 
 		this.on('mount', () => {
 			@fetch!
-			this.clock = set-interval @fetch, 60000ms
+			this.clock = setInterval @fetch, 60000ms
 
 		this.on('unmount', () => {
-			clear-interval @clock
+			clearInterval @clock
 
 		this.fetch = () => {
 			this.api CONFIG.url + '/api:rss' do
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index dbeac5eaf..b04068956 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -42,9 +42,9 @@
 		this.no-following = this.I.following_count == 0
 
 		this.on('mount', () => {
-			@stream.on 'post' this.on-stream-post
-			@stream.on 'follow' this.on-stream-follow
-			@stream.on 'unfollow' this.on-stream-unfollow
+			this.stream.on 'post' this.on-stream-post
+			this.stream.on 'follow' this.on-stream-follow
+			this.stream.on 'unfollow' this.on-stream-unfollow
 
 			document.addEventListener 'keydown' this.on-document-keydown
 			window.addEventListener 'scroll' this.on-scroll
@@ -53,9 +53,9 @@
 				this.trigger('loaded');
 
 		this.on('unmount', () => {
-			@stream.off 'post' this.on-stream-post
-			@stream.off 'follow' this.on-stream-follow
-			@stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off 'post' this.on-stream-post
+			this.stream.off 'follow' this.on-stream-follow
+			this.stream.off 'unfollow' this.on-stream-unfollow
 
 			document.removeEventListener 'keydown' this.on-document-keydown
 			window.removeEventListener 'scroll' this.on-scroll
diff --git a/src/web/app/desktop/tags/home-widgets/tips.tag b/src/web/app/desktop/tags/home-widgets/tips.tag
index 08e1b1737..6718c7063 100644
--- a/src/web/app/desktop/tags/home-widgets/tips.tag
+++ b/src/web/app/desktop/tags/home-widgets/tips.tag
@@ -43,10 +43,10 @@
 
 		this.on('mount', () => {
 			@set!
-			this.clock = set-interval @change, 20000ms
+			this.clock = setInterval @change, 20000ms
 
 		this.on('unmount', () => {
-			clear-interval @clock
+			clearInterval @clock
 
 		this.set = () => {
 			this.refs.text.innerHTML = @tips[Math.floor Math.random! * @tips.length]
diff --git a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
index f2a8a7476..19b6310ea 100644
--- a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
+++ b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
@@ -120,13 +120,13 @@
 
 		this.on('mount', () => {
 			@fetch!
-			this.clock = set-interval =>
+			this.clock = setInterval =>
 				if @users.length < @limit
 					@fetch true
 			, 60000ms
 
 		this.on('unmount', () => {
-			clear-interval @clock
+			clearInterval @clock
 
 		this.fetch = (quiet = false) => {
 			this.loading = true
@@ -134,7 +134,7 @@
 			if not quiet then this.update();
 			this.api 'users/recommendation' do
 				limit: @limit
-				offset: @limit * @page
+				offset: @limit * this.page
 			.then (users) =>
 				this.loading = false
 				this.users = users
@@ -146,7 +146,7 @@
 			if @users.length < @limit
 				this.page = 0
 			else
-				@page++
+				this.page++
 			@fetch!
 	</script>
 </mk-user-recommendation-home-widget>
diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag
index 729022073..3d0d9d415 100644
--- a/src/web/app/desktop/tags/home.tag
+++ b/src/web/app/desktop/tags/home.tag
@@ -62,7 +62,7 @@
 		this.mode = this.opts.mode || 'timeline' 
 
 		// https://github.com/riot/riot/issues/2080
-		if @mode == '' then this.mode = 'timeline' 
+		if this.mode == '' then this.mode = 'timeline' 
 
 		this.home = []
 
@@ -70,7 +70,7 @@
 			this.refs.tl.on('loaded', () => {
 				this.trigger('loaded');
 
-			this.I.data.home.for-each (widget) =>
+			this.I.data.home.forEach (widget) =>
 				try
 					el = document.createElement 'mk-' + widget.name + '-home-widget' 
 					switch widget.place
@@ -84,7 +84,7 @@
 					// noop
 
 		this.on('unmount', () => {
-			@home.for-each (widget) =>
+			@home.forEach (widget) =>
 				widget.unmount!
 	</script>
 </mk-home>
diff --git a/src/web/app/desktop/tags/notifications.tag b/src/web/app/desktop/tags/notifications.tag
index 39a33e410..39d86c5e2 100644
--- a/src/web/app/desktop/tags/notifications.tag
+++ b/src/web/app/desktop/tags/notifications.tag
@@ -194,19 +194,19 @@
 			.catch (err, text-status) ->
 				console.error err
 
-			@stream.on 'notification' this.on-notification
+			this.stream.on 'notification' this.on-notification
 
 		this.on('unmount', () => {
-			@stream.off 'notification' this.on-notification
+			this.stream.off 'notification' this.on-notification
 
 		this.on-notification = (notification) => {
 			@notifications.unshift notification
 			this.update();
 
 		this.on('update', () => {
-			@notifications.for-each (notification) =>
-				date = (new Date notification.created_at).get-date!
-				month = (new Date notification.created_at).get-month! + 1
+			@notifications.forEach (notification) =>
+				date = (new Date notification.created_at).getDate()
+				month = (new Date notification.created_at).getMonth() + 1
 				notification._date = date
 				notification._datetext = month + '月 ' + date + '日'
 	</script>
diff --git a/src/web/app/desktop/tags/pages/home.tag b/src/web/app/desktop/tags/pages/home.tag
index 3dd0b69d8..4ed74a373 100644
--- a/src/web/app/desktop/tags/pages/home.tag
+++ b/src/web/app/desktop/tags/pages/home.tag
@@ -27,11 +27,11 @@
 
 			document.title = 'Misskey'
 			this.Progress.start();
-			@stream.on 'post' this.on-stream-post
+			this.stream.on 'post' this.on-stream-post
 			document.addEventListener 'visibilitychange' @window-on-visibilitychange, false
 
 		this.on('unmount', () => {
-			@stream.off 'post' this.on-stream-post
+			this.stream.off 'post' this.on-stream-post
 			document.removeEventListener 'visibilitychange' @window-on-visibilitychange
 
 		this.on-stream-post = (post) => {
diff --git a/src/web/app/desktop/tags/post-detail-sub.tag b/src/web/app/desktop/tags/post-detail-sub.tag
index 1a6dbe069..b61898f67 100644
--- a/src/web/app/desktop/tags/post-detail-sub.tag
+++ b/src/web/app/desktop/tags/post-detail-sub.tag
@@ -110,31 +110,31 @@
 
 		this.post = this.opts.post
 
-		this.url = CONFIG.url + '/' + @post.user.username + '/' + @post.id
+		this.url = CONFIG.url + '/' + this.post.user.username + '/' + this.post.id
 
-		this.title = @date-stringify @post.created_at
+		this.title = @date-stringify this.post.created_at
 
 		this.on('mount', () => {
-			if @post.text?
-				tokens = @analyze @post.text
+			if this.post.text?
+				tokens = @analyze this.post.text
 				this.refs.text.innerHTML = @compile tokens
 
-				this.refs.text.children.for-each (e) =>
+				this.refs.text.children.forEach (e) =>
 					if e.tag-name == 'MK-URL' 
 						riot.mount e
 
 		this.like = () => {
-			if @post.is_liked
+			if this.post.is_liked
 				this.api 'posts/likes/delete' do
-					post_id: @post.id
+					post_id: this.post.id
 				.then =>
-					@post.is_liked = false
+					this.post.is_liked = false
 					this.update();
 			else
 				this.api 'posts/likes/create' do
-					post_id: @post.id
+					post_id: this.post.id
 				.then =>
-					@post.is_liked = true
+					this.post.is_liked = true
 					this.update();
 	</script>
 </mk-post-detail-sub>
diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag
index c835521ad..958b0c681 100644
--- a/src/web/app/desktop/tags/post-detail.tag
+++ b/src/web/app/desktop/tags/post-detail.tag
@@ -349,18 +349,18 @@
 				this.post = post
 				this.trigger('loaded');
 
-				this.is-repost = @post.repost?
-				this.p = if @is-repost then @post.repost else @post
+				this.is-repost = this.post.repost?
+				this.p = if @is-repost then this.post.repost else this.post
 
-				this.title = @date-stringify @p.created_at
+				this.title = @date-stringify this.p.created_at
 
 				this.update();
 
-				if @p.text?
-					tokens = @analyze @p.text
+				if this.p.text?
+					tokens = @analyze this.p.text
 					this.refs.text.innerHTML = @compile tokens
 
-					this.refs.text.children.for-each (e) =>
+					this.refs.text.children.forEach (e) =>
 						if e.tag-name == 'MK-URL' 
 							riot.mount e
 
@@ -369,12 +369,12 @@
 						.filter (t) -> t.type == 'link' 
 						.map (t) =>
 							this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-							riot.mount @preview, do
+							riot.mount this.preview, do
 								url: t.content
 
 				// Get likes
 				this.api 'posts/likes' do
-					post_id: @p.id
+					post_id: this.p.id
 					limit: 8
 				.then (likes) =>
 					this.likes = likes
@@ -382,7 +382,7 @@
 
 				// Get reposts
 				this.api 'posts/reposts' do
-					post_id: @p.id
+					post_id: this.p.id
 					limit: 8
 				.then (reposts) =>
 					this.reposts = reposts
@@ -390,7 +390,7 @@
 
 				// Get replies
 				this.api 'posts/replies' do
-					post_id: @p.id
+					post_id: this.p.id
 					limit: 8
 				.then (replies) =>
 					this.replies = replies
@@ -401,25 +401,25 @@
 		this.reply = () => {
 			form = document.body.appendChild document.createElement 'mk-post-form-window' 
 			riot.mount form, do
-				reply: @p
+				reply: this.p
 
 		this.repost = () => {
 			form = document.body.appendChild document.createElement 'mk-repost-form-window' 
 			riot.mount form, do
-				post: @p
+				post: this.p
 
 		this.like = () => {
-			if @p.is_liked
+			if this.p.is_liked
 				this.api 'posts/likes/delete' do
-					post_id: @p.id
+					post_id: this.p.id
 				.then =>
-					@p.is_liked = false
+					this.p.is_liked = false
 					this.update();
 			else
 				this.api 'posts/likes/create' do
-					post_id: @p.id
+					post_id: this.p.id
 				.then =>
-					@p.is_liked = true
+					this.p.is_liked = true
 					this.update();
 
 		this.load-context = () => {
@@ -427,7 +427,7 @@
 
 			// Get context
 			this.api 'posts/context' do
-				post_id: @p.reply_to_id
+				post_id: this.p.reply_to_id
 			.then (context) =>
 				this.context = context.reverse!
 				this.loading-context = false
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index d49feba14..ed56e2a11 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -348,7 +348,7 @@
 			e.stopPropagation();
 			this.draghover = true
 			// ドラッグされてきたものがファイルだったら
-			if e.dataTransfer.effect-allowed == 'all' 
+			if e.dataTransfer.effectAllowed == 'all' 
 				e.dataTransfer.dropEffect = 'copy' 
 			else
 				e.dataTransfer.dropEffect = 'move' 
@@ -367,7 +367,7 @@
 
 			// ファイルだったら
 			if e.dataTransfer.files.length > 0
-				Array.prototype.for-each.call e.dataTransfer.files, (file) =>
+				Array.prototype.forEach.call e.dataTransfer.files, (file) =>
 					@upload file
 				return false
 
@@ -390,7 +390,7 @@
 
 		this.onkeydown = (e) => {
 			if (e.which == 10 || e.which == 13) && (e.ctrlKey || e.meta-key)
-				@post!
+				this.post!
 
 		this.onpaste = (e) => {
 			data = e.clipboardData
@@ -402,14 +402,14 @@
 						@upload item.getAsFile();
 
 		this.select-file = () => {
-			this.refs.file.click!
+			this.refs.file.click();
 
 		this.select-file-from-drive = () => {
 			browser = document.body.appendChild document.createElement 'mk-select-file-from-drive-window' 
 			i = riot.mount browser, do
 				multiple: true
 			i[0].one 'selected' (files) =>
-				files.for-each @add-file
+				files.forEach @add-file
 
 		this.change-file = () => {
 			files = this.refs.file.files
@@ -448,7 +448,7 @@
 				text: this.refs.text.value
 				media_ids: files
 				reply_to_id: if @in-reply-to-post? then @in-reply-to-post.id else undefined
-				poll: if @poll then this.refs.poll.get! else undefined
+				poll: if this.poll then this.refs.poll.get! else undefined
 			.then (data) =>
 				this.trigger('post');
 				@notify if @in-reply-to-post? then '返信しました!' else '投稿しました!'
diff --git a/src/web/app/desktop/tags/post-preview.tag b/src/web/app/desktop/tags/post-preview.tag
index 5ee0a6065..06008da3c 100644
--- a/src/web/app/desktop/tags/post-preview.tag
+++ b/src/web/app/desktop/tags/post-preview.tag
@@ -88,6 +88,6 @@
 
 		this.post = this.opts.post
 
-		this.title = @date-stringify @post.created_at
+		this.title = @date-stringify this.post.created_at
 	</script>
 </mk-post-preview>
diff --git a/src/web/app/desktop/tags/post-status-graph.tag b/src/web/app/desktop/tags/post-status-graph.tag
index 039c676b1..f4a890a0c 100644
--- a/src/web/app/desktop/tags/post-status-graph.tag
+++ b/src/web/app/desktop/tags/post-status-graph.tag
@@ -16,24 +16,24 @@
 		this.post-promise = if @is-promise this.opts.post then this.opts.post else Promise.resolve this.opts.post
 
 		this.on('mount', () => {
-			post <~ @post-promise.then
+			post <~ this.post-promise.then
 			this.post = post
 			this.update();
 
 			this.api 'aggregation/posts/like' do
-				post_id: @post.id
+				post_id: this.post.id
 				limit: 30days
 			.then (likes) =>
 				likes = likes.reverse!
 
 				this.api 'aggregation/posts/repost' do
-					post_id: @post.id
+					post_id: this.post.id
 					limit: 30days
 				.then (repost) =>
 					repost = repost.reverse!
 
 					this.api 'aggregation/posts/reply' do
-						post_id: @post.id
+						post_id: this.post.id
 						limit: 30days
 					.then (replies) =>
 						replies = replies.reverse!
diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag
index a450e8a02..c56caa05e 100644
--- a/src/web/app/desktop/tags/search-posts.tag
+++ b/src/web/app/desktop/tags/search-posts.tag
@@ -63,16 +63,16 @@
 					this.refs.timeline.focus();
 
 		this.more = () => {
-			if @more-loading or @is-loading or @timeline.posts.length == 0
+			if @more-loading or @is-loading or this.timeline.posts.length == 0
 				return
 			this.more-loading = true
 			this.update();
 			this.api 'posts/search' do
 				query: @query
-				page: @page + 1
+				page: this.page + 1
 			.then (posts) =>
 				this.more-loading = false
-				@page++
+				this.page++
 				this.update();
 				this.refs.timeline.prepend-posts posts
 			.catch (err) =>
diff --git a/src/web/app/desktop/tags/stream-indicator.tag b/src/web/app/desktop/tags/stream-indicator.tag
index caa727dd8..c3669c074 100644
--- a/src/web/app/desktop/tags/stream-indicator.tag
+++ b/src/web/app/desktop/tags/stream-indicator.tag
@@ -35,7 +35,7 @@
 			if @state == 'connected' 
 				this.root.style.opacity = 0
 
-		@stream-state-ev.on('connected', () => {
+		this.stream-state-ev.on('connected', () => {
 			this.state = @get-stream-state!
 			this.update();
 			setTimeout =>
@@ -44,7 +44,7 @@
 				} 200ms 'linear' 
 			, 1000ms
 
-		@stream-state-ev.on('closed', () => {
+		this.stream-state-ev.on('closed', () => {
 			this.state = @get-stream-state!
 			this.update();
 			Velocity this.root, {
diff --git a/src/web/app/desktop/tags/sub-post-content.tag b/src/web/app/desktop/tags/sub-post-content.tag
index 0fdd049ec..8d4a06b49 100644
--- a/src/web/app/desktop/tags/sub-post-content.tag
+++ b/src/web/app/desktop/tags/sub-post-content.tag
@@ -34,11 +34,11 @@
 		this.post = this.opts.post
 
 		this.on('mount', () => {
-			if @post.text?
-				tokens = @analyze @post.text
+			if this.post.text?
+				tokens = @analyze this.post.text
 				this.refs.text.innerHTML = @compile tokens, false
 
-				this.refs.text.children.for-each (e) =>
+				this.refs.text.children.forEach (e) =>
 					if e.tag-name == 'MK-URL' 
 						riot.mount e
 	</script>
diff --git a/src/web/app/desktop/tags/timeline-post-sub.tag b/src/web/app/desktop/tags/timeline-post-sub.tag
index bdeffea18..2c76527f1 100644
--- a/src/web/app/desktop/tags/timeline-post-sub.tag
+++ b/src/web/app/desktop/tags/timeline-post-sub.tag
@@ -14,7 +14,7 @@
 
 		this.post = this.opts.post
 
-		this.title = @date-stringify @post.created_at
+		this.title = @date-stringify this.post.created_at
 
 	</script>
 	<style>
diff --git a/src/web/app/desktop/tags/timeline-post.tag b/src/web/app/desktop/tags/timeline-post.tag
index 5efc05063..6f5841a76 100644
--- a/src/web/app/desktop/tags/timeline-post.tag
+++ b/src/web/app/desktop/tags/timeline-post.tag
@@ -319,25 +319,25 @@
 		this.mixin('NotImplementedException');
 
 		this.post = this.opts.post
-		this.is-repost = @post.repost? and !@post.text?
-		this.p = if @is-repost then @post.repost else @post
+		this.is-repost = this.post.repost? and !this.post.text?
+		this.p = if @is-repost then this.post.repost else this.post
 
-		this.title = @date-stringify @p.created_at
+		this.title = @date-stringify this.p.created_at
 
-		this.url = CONFIG.url + '/' + @p.user.username + '/' + @p.id
+		this.url = CONFIG.url + '/' + this.p.user.username + '/' + this.p.id
 		this.is-detail-opened = false
 
 		this.on('mount', () => {
-			if @p.text?
-				tokens = if @p._highlight?
-					then @analyze @p._highlight
-					else @analyze @p.text
+			if this.p.text?
+				tokens = if this.p._highlight?
+					then @analyze this.p._highlight
+					else @analyze this.p.text
 
-				this.refs.text.innerHTML = this.refs.text.innerHTML.replace '<p class="dummy"></p>' if @p._highlight?
+				this.refs.text.innerHTML = this.refs.text.innerHTML.replace '<p class="dummy"></p>' if this.p._highlight?
 					then @compile tokens, true, false
 					else @compile tokens
 
-				this.refs.text.children.for-each (e) =>
+				this.refs.text.children.forEach (e) =>
 					if e.tag-name == 'MK-URL' 
 						riot.mount e
 
@@ -346,31 +346,31 @@
 					.filter (t) -> t.type == 'link' 
 					.map (t) =>
 						this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-						riot.mount @preview, do
+						riot.mount this.preview, do
 							url: t.content
 
 		this.reply = () => {
 			form = document.body.appendChild document.createElement 'mk-post-form-window' 
 			riot.mount form, do
-				reply: @p
+				reply: this.p
 
 		this.repost = () => {
 			form = document.body.appendChild document.createElement 'mk-repost-form-window' 
 			riot.mount form, do
-				post: @p
+				post: this.p
 
 		this.like = () => {
-			if @p.is_liked
+			if this.p.is_liked
 				this.api 'posts/likes/delete' do
-					post_id: @p.id
+					post_id: this.p.id
 				.then =>
-					@p.is_liked = false
+					this.p.is_liked = false
 					this.update();
 			else
 				this.api 'posts/likes/create' do
-					post_id: @p.id
+					post_id: this.p.id
 				.then =>
-					@p.is_liked = true
+					this.p.is_liked = true
 					this.update();
 
 		this.toggle-detail = () => {
@@ -381,9 +381,9 @@
 			should-be-cancel = true
 			switch
 			| e.which == 38 or e.which == 74 or (e.which == 9 and e.shift-key) => // ↑, j or Shift+Tab
-				focus this.root, (e) -> e.previous-element-sibling
+				focus this.root, (e) -> e.previousElementSibling
 			| e.which == 40 or e.which == 75 or e.which == 9 => // ↓, k or Tab
-				focus this.root, (e) -> e.next-element-sibling
+				focus this.root, (e) -> e.nextElementSibling
 			| e.which == 81 or e.which == 69 => // q or e
 				@repost!
 			| e.which == 70 or e.which == 76 => // f or l
diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag
index ebc6249c6..f63afabd4 100644
--- a/src/web/app/desktop/tags/timeline.tag
+++ b/src/web/app/desktop/tags/timeline.tag
@@ -51,12 +51,12 @@
 			this.update();
 
 		this.prepend-posts = (posts) => {
-			posts.for-each (post) =>
-				@posts.push post
+			posts.forEach (post) =>
+				this.posts.push post
 				this.update();
 
 		this.add-post = (post) => {
-			@posts.unshift post
+			this.posts.unshift post
 			this.update();
 
 		this.clear = () => {
@@ -67,13 +67,13 @@
 			this.root.children.0.focus();
 
 		this.on('update', () => {
-			@posts.for-each (post) =>
-				date = (new Date post.created_at).get-date!
-				month = (new Date post.created_at).get-month! + 1
+			this.posts.forEach (post) =>
+				date = (new Date post.created_at).getDate()
+				month = (new Date post.created_at).getMonth() + 1
 				post._date = date
 				post._datetext = month + '月 ' + date + '日'
 
 		this.tail = () => {
-			@posts[@posts.length - 1]
+			this.posts[this.posts.length - 1]
 	</script>
 </mk-timeline>
diff --git a/src/web/app/desktop/tags/ui-header-account.tag b/src/web/app/desktop/tags/ui-header-account.tag
index e6ededc75..21382bc53 100644
--- a/src/web/app/desktop/tags/ui-header-account.tag
+++ b/src/web/app/desktop/tags/ui-header-account.tag
@@ -177,14 +177,14 @@
 			this.is-open = true
 			this.update();
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) =>
+			Array.prototype.forEach.call all, (el) =>
 				el.addEventListener 'mousedown' @mousedown
 
 		this.close = () => {
 			this.is-open = false
 			this.update();
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) =>
+			Array.prototype.forEach.call all, (el) =>
 				el.removeEventListener 'mousedown' @mousedown
 
 		this.mousedown = (e) => {
diff --git a/src/web/app/desktop/tags/ui-header-clock.tag b/src/web/app/desktop/tags/ui-header-clock.tag
index 5b42cefbb..74336b460 100644
--- a/src/web/app/desktop/tags/ui-header-clock.tag
+++ b/src/web/app/desktop/tags/ui-header-clock.tag
@@ -59,15 +59,15 @@
 	</style>
 	<script>
 		this.draw = () => {
-			now = new Date!
+			const now = new Date();
 
-			yyyy = now.get-full-year!
-			mm = (\0 + (now.get-month! + 1)).slice -2
-			dd = (\0 + now.get-date!).slice -2
+			yyyy = now.getFullYear()
+			mm = (\0 + (now.getMonth() + 1)).slice -2
+			dd = (\0 + now.getDate()).slice -2
 			yyyymmdd = "<span class='yyyymmdd'>#yyyy/#mm/#dd</span>"
 
-			hh = (\0 + now.get-hours!).slice -2
-			mm = (\0 + now.get-minutes!).slice -2
+			hh = (\0 + now.getHours()).slice -2
+			mm = (\0 + now.getMinutes()).slice -2
 			hhmm = "<span class='hhmm'>#hh:#mm</span>"
 
 			if now.get-seconds! % 2 == 0
@@ -79,9 +79,9 @@
 
 		this.on('mount', () => {
 			@draw!
-			this.clock = set-interval @draw, 1000ms
+			this.clock = setInterval @draw, 1000ms
 
 		this.on('unmount', () => {
-			clear-interval @clock
+			clearInterval @clock
 	</script>
 </mk-ui-header-clock>
diff --git a/src/web/app/desktop/tags/ui-header-nav.tag b/src/web/app/desktop/tags/ui-header-nav.tag
index 88607d6a5..a884aa0b2 100644
--- a/src/web/app/desktop/tags/ui-header-nav.tag
+++ b/src/web/app/desktop/tags/ui-header-nav.tag
@@ -84,8 +84,8 @@
 			this.page = this.opts.page
 
 			this.on('mount', () => {
-				@stream.on 'read_all_messaging_messages' this.on-read-all-messaging-messages
-				@stream.on 'unread_messaging_message' this.on-unread-messaging-message
+				this.stream.on 'read_all_messaging_messages' this.on-read-all-messaging-messages
+				this.stream.on 'unread_messaging_message' this.on-unread-messaging-message
 
 				// Fetch count of unread messaging messages
 				this.api 'messaging/unread' 
@@ -95,8 +95,8 @@
 						this.update();
 
 			this.on('unmount', () => {
-				@stream.off 'read_all_messaging_messages' this.on-read-all-messaging-messages
-				@stream.off 'unread_messaging_message' this.on-unread-messaging-message
+				this.stream.off 'read_all_messaging_messages' this.on-read-all-messaging-messages
+				this.stream.off 'unread_messaging_message' this.on-unread-messaging-message
 
 			this.on-read-all-messaging-messages = () => {
 				this.has-unread-messaging-messages = false
diff --git a/src/web/app/desktop/tags/ui-header-notifications.tag b/src/web/app/desktop/tags/ui-header-notifications.tag
index 0a355e022..fac90bb83 100644
--- a/src/web/app/desktop/tags/ui-header-notifications.tag
+++ b/src/web/app/desktop/tags/ui-header-notifications.tag
@@ -87,14 +87,14 @@
 			this.is-open = true
 			this.update();
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) =>
+			Array.prototype.forEach.call all, (el) =>
 				el.addEventListener 'mousedown' @mousedown
 
 		this.close = () => {
 			this.is-open = false
 			this.update();
 			all = document.query-selector-all 'body *'
-			Array.prototype.for-each.call all, (el) =>
+			Array.prototype.forEach.call all, (el) =>
 				el.removeEventListener 'mousedown' @mousedown
 
 		this.mousedown = (e) => {
diff --git a/src/web/app/desktop/tags/ui-header-search.tag b/src/web/app/desktop/tags/ui-header-search.tag
index cc8ca2ae0..f7e2842c7 100644
--- a/src/web/app/desktop/tags/ui-header-search.tag
+++ b/src/web/app/desktop/tags/ui-header-search.tag
@@ -36,6 +36,6 @@
 
 		this.onsubmit = (e) => {
 			e.preventDefault();
-			@page '/search:' + this.refs.q.value
+			this.page '/search:' + this.refs.q.value
 	</script>
 </mk-ui-header-search>
diff --git a/src/web/app/desktop/tags/user-photos.tag b/src/web/app/desktop/tags/user-photos.tag
index 89453b460..71899c92e 100644
--- a/src/web/app/desktop/tags/user-photos.tag
+++ b/src/web/app/desktop/tags/user-photos.tag
@@ -77,8 +77,8 @@
 					limit: 9posts
 				.then (posts) =>
 					this.initializing = false
-					posts.for-each (post) =>
-						post.media.for-each (image) =>
+					posts.forEach (post) =>
+						post.media.forEach (image) =>
 							if @images.length < 9
 								@images.push image
 					this.update();
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index ab82b2677..c982a68a7 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -84,7 +84,7 @@
 		this.fetch = (cb) => {
 			this.api 'users/posts' do
 				user_id: @user.id
-				with_replies: @mode == 'with-replies' 
+				with_replies: this.mode == 'with-replies' 
 			.then (posts) =>
 				this.is-loading = false
 				this.is-empty = posts.length == 0
@@ -102,7 +102,7 @@
 			this.update();
 			this.api 'users/posts' do
 				user_id: @user.id
-				with_replies: @mode == 'with-replies' 
+				with_replies: this.mode == 'with-replies' 
 				max_id: this.refs.timeline.tail!.id
 			.then (posts) =>
 				this.more-loading = false
diff --git a/src/web/app/desktop/tags/users-list.tag b/src/web/app/desktop/tags/users-list.tag
index 9fd123952..dbb7069c4 100644
--- a/src/web/app/desktop/tags/users-list.tag
+++ b/src/web/app/desktop/tags/users-list.tag
@@ -104,7 +104,7 @@
 			this.fetching = true
 			this.update();
 			obj <~ this.opts.fetch do
-				@mode == 'iknow' 
+				this.mode == 'iknow' 
 				@limit
 				null
 			this.users = obj.users
@@ -117,7 +117,7 @@
 			this.more-fetching = true
 			this.update();
 			obj <~ this.opts.fetch do
-				@mode == 'iknow' 
+				this.mode == 'iknow' 
 				@limit
 				@cursor
 			this.users = @users.concat obj.users
diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index 81011e9f5..3c7cc14f7 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -304,7 +304,7 @@
 			z = 0
 
 			ws = document.query-selector-all 'mk-window' 
-			ws.for-each (w) !=>
+			ws.forEach (w) !=>
 				if w == this.root then return
 				m = w.query-selector ':scope > .main'
 				mz = Number(document.default-view.get-computed-style m, null .z-index)
diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag
index 2718bcd5d..d0906d638 100644
--- a/src/web/app/dev/tags/new-app-form.tag
+++ b/src/web/app/dev/tags/new-app-form.tag
@@ -222,7 +222,7 @@
 			cb = this.refs.cb.value
 			permission = []
 
-			this.refs.permission.query-selector-all 'input' .for-each (el) =>
+			this.refs.permission.query-selector-all 'input' .forEach (el) =>
 				if el.checked then permission.push el.value
 
 			locker = document.body.appendChild document.createElement 'mk-locker' 
diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag
index 6daa50c26..d0c9b87b9 100644
--- a/src/web/app/mobile/tags/drive.tag
+++ b/src/web/app/mobile/tags/drive.tag
@@ -133,7 +133,7 @@
 
 		this.files = []
 		this.folders = []
-		this.hierarchy-folders = []
+		this.hierarchyFolders = []
 		this.selected-files = []
 
 		// 現在の階層(フォルダ)
@@ -146,10 +146,10 @@
 		this.multiple = if this.opts.multiple? then this.opts.multiple else false
 
 		this.on('mount', () => {
-			@stream.on 'drive_file_created' this.on-stream-drive-file-created
-			@stream.on 'drive_file_updated' this.on-stream-drive-file-updated
-			@stream.on 'drive_folder_created' this.on-stream-drive-folder-created
-			@stream.on 'drive_folder_updated' this.on-stream-drive-folder-updated
+			this.stream.on 'drive_file_created' this.on-stream-drive-file-created
+			this.stream.on 'drive_file_updated' this.on-stream-drive-file-updated
+			this.stream.on 'drive_folder_created' this.on-stream-drive-folder-created
+			this.stream.on 'drive_folder_updated' this.on-stream-drive-folder-updated
 
 			// Riotのバグでnullを渡しても""になる
 			// https://github.com/riot/riot/issues/2080
@@ -162,10 +162,10 @@
 				@load!
 
 		this.on('unmount', () => {
-			@stream.off 'drive_file_created' this.on-stream-drive-file-created
-			@stream.off 'drive_file_updated' this.on-stream-drive-file-updated
-			@stream.off 'drive_folder_created' this.on-stream-drive-folder-created
-			@stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
+			this.stream.off 'drive_file_created' this.on-stream-drive-file-created
+			this.stream.off 'drive_file_updated' this.on-stream-drive-file-updated
+			this.stream.off 'drive_folder_created' this.on-stream-drive-folder-created
+			this.stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
 
 		this.on-stream-drive-file-created = (file) => {
 			@add-file file, true
@@ -210,10 +210,10 @@
 				folder_id: target-folder
 			.then (folder) =>
 				this.folder = folder
-				this.hierarchy-folders = []
+				this.hierarchyFolders = []
 
 				x = (f) =>
-					@hierarchy-folders.unshift f
+					@hierarchyFolders.unshift f
 					if f.parent?
 						x f.parent
 
@@ -275,7 +275,7 @@
 			if this.folder != null or this.file != null
 				this.file = null
 				this.folder = null
-				this.hierarchy-folders = []
+				this.hierarchyFolders = []
 				this.update();
 				this.trigger('move-root');
 				@load!
@@ -325,9 +325,9 @@
 			flag = false
 			complete = =>
 				if flag
-					load-folders.for-each (folder) =>
+					load-folders.forEach (folder) =>
 						@add-folder folder
-					load-files.for-each (file) =>
+					load-files.forEach (file) =>
 						@add-file file
 					this.loading = false
 					this.update();
@@ -361,10 +361,10 @@
 			.then (file) =>
 				this.file = file
 				this.folder = null
-				this.hierarchy-folders = []
+				this.hierarchyFolders = []
 
 				x = (f) =>
-					@hierarchy-folders.unshift f
+					@hierarchyFolders.unshift f
 					if f.parent?
 						x f.parent
 
diff --git a/src/web/app/mobile/tags/follow-button.tag b/src/web/app/mobile/tags/follow-button.tag
index 36447f3ac..71a38254d 100644
--- a/src/web/app/mobile/tags/follow-button.tag
+++ b/src/web/app/mobile/tags/follow-button.tag
@@ -62,12 +62,12 @@
 				this.user = user
 				this.init = false
 				this.update();
-				@stream.on 'follow' this.on-stream-follow
-				@stream.on 'unfollow' this.on-stream-unfollow
+				this.stream.on 'follow' this.on-stream-follow
+				this.stream.on 'unfollow' this.on-stream-unfollow
 
 		this.on('unmount', () => {
-			@stream.off 'follow' this.on-stream-follow
-			@stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off 'follow' this.on-stream-follow
+			this.stream.off 'unfollow' this.on-stream-unfollow
 
 		this.on-stream-follow = (user) => {
 			if user.id == @user.id
diff --git a/src/web/app/mobile/tags/home-timeline.tag b/src/web/app/mobile/tags/home-timeline.tag
index 322ba8f93..b308c4168 100644
--- a/src/web/app/mobile/tags/home-timeline.tag
+++ b/src/web/app/mobile/tags/home-timeline.tag
@@ -16,14 +16,14 @@
 				this.trigger('loaded');
 
 		this.on('mount', () => {
-			@stream.on 'post' this.on-stream-post
-			@stream.on 'follow' this.on-stream-follow
-			@stream.on 'unfollow' this.on-stream-unfollow
+			this.stream.on 'post' this.on-stream-post
+			this.stream.on 'follow' this.on-stream-follow
+			this.stream.on 'unfollow' this.on-stream-unfollow
 
 		this.on('unmount', () => {
-			@stream.off 'post' this.on-stream-post
-			@stream.off 'follow' this.on-stream-follow
-			@stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off 'post' this.on-stream-post
+			this.stream.off 'follow' this.on-stream-follow
+			this.stream.off 'unfollow' this.on-stream-unfollow
 
 		this.more = () => {
 			this.api 'posts/timeline' do
diff --git a/src/web/app/mobile/tags/notifications.tag b/src/web/app/mobile/tags/notifications.tag
index 9d665ec93..ef53c025e 100644
--- a/src/web/app/mobile/tags/notifications.tag
+++ b/src/web/app/mobile/tags/notifications.tag
@@ -74,19 +74,19 @@
 			.catch (err, text-status) ->
 				console.error err
 
-			@stream.on 'notification' this.on-notification
+			this.stream.on 'notification' this.on-notification
 
 		this.on('unmount', () => {
-			@stream.off 'notification' this.on-notification
+			this.stream.off 'notification' this.on-notification
 
 		this.on-notification = (notification) => {
 			@notifications.unshift notification
 			this.update();
 
 		this.on('update', () => {
-			@notifications.for-each (notification) =>
-				date = (new Date notification.created_at).get-date!
-				month = (new Date notification.created_at).get-month! + 1
+			@notifications.forEach (notification) =>
+				date = (new Date notification.created_at).getDate()
+				month = (new Date notification.created_at).getMonth() + 1
 				notification._date = date
 				notification._datetext = month + '月 ' + date + '日'
 	</script>
diff --git a/src/web/app/mobile/tags/page/home.tag b/src/web/app/mobile/tags/page/home.tag
index d46e83474..ac00800a1 100644
--- a/src/web/app/mobile/tags/page/home.tag
+++ b/src/web/app/mobile/tags/page/home.tag
@@ -22,14 +22,14 @@
 
 			this.Progress.start();
 
-			@stream.on 'post' this.on-stream-post
+			this.stream.on 'post' this.on-stream-post
 			document.addEventListener 'visibilitychange' @window-on-visibilitychange, false
 
 			this.refs.ui.refs.home.on('loaded', () => {
 				this.Progress.done();
 
 		this.on('unmount', () => {
-			@stream.off 'post' this.on-stream-post
+			this.stream.off 'post' this.on-stream-post
 			document.removeEventListener 'visibilitychange' @window-on-visibilitychange
 
 		this.on-stream-post = (post) => {
diff --git a/src/web/app/mobile/tags/page/messaging.tag b/src/web/app/mobile/tags/page/messaging.tag
index 1af983b1d..78a2ca991 100644
--- a/src/web/app/mobile/tags/page/messaging.tag
+++ b/src/web/app/mobile/tags/page/messaging.tag
@@ -15,7 +15,7 @@
 			this.ui.trigger('title', '<i class="fa fa-comments-o"></i>メッセージ');
 
 			this.refs.ui.refs.index.on('navigate-user', (user) => {
-				@page '/i/messaging/' + user.username
+				this.page '/i/messaging/' + user.username
 
 	</script>
 </mk-messaging-page>
diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag
index 9319cfe68..fee132d7d 100644
--- a/src/web/app/mobile/tags/post-detail.tag
+++ b/src/web/app/mobile/tags/post-detail.tag
@@ -344,18 +344,18 @@
 				post_id: this.opts.post
 			.then (post) =>
 				this.post = post
-				this.is-repost = @post.repost?
-				this.p = if @is-repost then @post.repost else @post
-				this.summary = @get-post-summary @p
+				this.is-repost = this.post.repost?
+				this.p = if @is-repost then this.post.repost else this.post
+				this.summary = @get-post-summary this.p
 				this.trigger('loaded');
 				this.fetching = false
 				this.update();
 
-				if @p.text?
-					tokens = @analyze @p.text
+				if this.p.text?
+					tokens = @analyze this.p.text
 					this.refs.text.innerHTML = @compile tokens
 
-					this.refs.text.children.for-each (e) =>
+					this.refs.text.children.forEach (e) =>
 						if e.tag-name == 'MK-URL' 
 							riot.mount e
 
@@ -364,12 +364,12 @@
 						.filter (t) -> t.type == 'link' 
 						.map (t) =>
 							this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-							riot.mount @preview, do
+							riot.mount this.preview, do
 								url: t.content
 
 				// Get likes
 				this.api 'posts/likes' do
-					post_id: @p.id
+					post_id: this.p.id
 					limit: 8
 				.then (likes) =>
 					this.likes = likes
@@ -377,7 +377,7 @@
 
 				// Get reposts
 				this.api 'posts/reposts' do
-					post_id: @p.id
+					post_id: this.p.id
 					limit: 8
 				.then (reposts) =>
 					this.reposts = reposts
@@ -385,7 +385,7 @@
 
 				// Get replies
 				this.api 'posts/replies' do
-					post_id: @p.id
+					post_id: this.p.id
 					limit: 8
 				.then (replies) =>
 					this.replies = replies
@@ -393,27 +393,27 @@
 
 		this.reply = () => {
 			@open-post-form do
-				reply: @p
+				reply: this.p
 
 		this.repost = () => {
 			text = window.prompt '「' + @summary + '」をRepost'
 			if text?
 				this.api 'posts/create' do
-					repost_id: @p.id
+					repost_id: this.p.id
 					text: if text == '' then undefined else text
 
 		this.like = () => {
-			if @p.is_liked
+			if this.p.is_liked
 				this.api 'posts/likes/delete' do
-					post_id: @p.id
+					post_id: this.p.id
 				.then =>
-					@p.is_liked = false
+					this.p.is_liked = false
 					this.update();
 			else
 				this.api 'posts/likes/create' do
-					post_id: @p.id
+					post_id: this.p.id
 				.then =>
-					@p.is_liked = true
+					this.p.is_liked = true
 					this.update();
 
 		this.load-context = () => {
@@ -421,7 +421,7 @@
 
 			// Get context
 			this.api 'posts/context' do
-				post_id: @p.reply_to_id
+				post_id: this.p.reply_to_id
 			.then (context) =>
 				this.context = context.reverse!
 				this.loading-context = false
diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag
index 7b7243cf0..05cb1c565 100644
--- a/src/web/app/mobile/tags/post-form.tag
+++ b/src/web/app/mobile/tags/post-form.tag
@@ -202,7 +202,7 @@
 
 		this.onkeypress = (e) => {
 			if (e.char-code == 10 || e.char-code == 13) && e.ctrlKey
-				@post!
+				this.post!
 			else
 				return true
 
@@ -217,7 +217,7 @@
 			return true
 
 		this.select-file = () => {
-			this.refs.file.click!
+			this.refs.file.click();
 
 		this.select-file-from-drive = () => {
 			browser = document.body.appendChild document.createElement 'mk-drive-selector' 
@@ -225,7 +225,7 @@
 				multiple: true
 			.0
 			browser.on('selected', (files) => {
-				files.for-each @add-file
+				files.forEach @add-file
 
 		this.change-file = () => {
 			files = this.refs.file.files
@@ -264,7 +264,7 @@
 				text: this.refs.text.value
 				media_ids: files
 				reply_to_id: if this.opts.reply? then this.opts.reply.id else undefined
-				poll: if @poll then this.refs.poll.get! else undefined
+				poll: if this.poll then this.refs.poll.get! else undefined
 			.then (data) =>
 				this.trigger('post');
 				this.unmount();
diff --git a/src/web/app/mobile/tags/stream-indicator.tag b/src/web/app/mobile/tags/stream-indicator.tag
index caa727dd8..c3669c074 100644
--- a/src/web/app/mobile/tags/stream-indicator.tag
+++ b/src/web/app/mobile/tags/stream-indicator.tag
@@ -35,7 +35,7 @@
 			if @state == 'connected' 
 				this.root.style.opacity = 0
 
-		@stream-state-ev.on('connected', () => {
+		this.stream-state-ev.on('connected', () => {
 			this.state = @get-stream-state!
 			this.update();
 			setTimeout =>
@@ -44,7 +44,7 @@
 				} 200ms 'linear' 
 			, 1000ms
 
-		@stream-state-ev.on('closed', () => {
+		this.stream-state-ev.on('closed', () => {
 			this.state = @get-stream-state!
 			this.update();
 			Velocity this.root, {
diff --git a/src/web/app/mobile/tags/sub-post-content.tag b/src/web/app/mobile/tags/sub-post-content.tag
index 91bd5ac1d..a5af90cc7 100644
--- a/src/web/app/mobile/tags/sub-post-content.tag
+++ b/src/web/app/mobile/tags/sub-post-content.tag
@@ -33,11 +33,11 @@
 		this.post = this.opts.post
 
 		this.on('mount', () => {
-			if @post.text?
-				tokens = @analyze @post.text
+			if this.post.text?
+				tokens = @analyze this.post.text
 				this.refs.text.innerHTML = @compile tokens, false
 
-				this.refs.text.children.for-each (e) =>
+				this.refs.text.children.forEach (e) =>
 					if e.tag-name == 'MK-URL' 
 						riot.mount e
 	</script>
diff --git a/src/web/app/mobile/tags/timeline-post.tag b/src/web/app/mobile/tags/timeline-post.tag
index 9cc6a088b..2d6a6a1fa 100644
--- a/src/web/app/mobile/tags/timeline-post.tag
+++ b/src/web/app/mobile/tags/timeline-post.tag
@@ -292,22 +292,22 @@
 		this.mixin('open-post-form');
 
 		this.post = this.opts.post
-		this.is-repost = @post.repost? and !@post.text?
-		this.p = if @is-repost then @post.repost else @post
-		this.summary = @get-post-summary @p
-		this.url = CONFIG.url + '/' + @p.user.username + '/' + @p.id
+		this.is-repost = this.post.repost? and !this.post.text?
+		this.p = if @is-repost then this.post.repost else this.post
+		this.summary = @get-post-summary this.p
+		this.url = CONFIG.url + '/' + this.p.user.username + '/' + this.p.id
 
 		this.on('mount', () => {
-			if @p.text?
-				tokens = if @p._highlight?
-					then @analyze @p._highlight
-					else @analyze @p.text
+			if this.p.text?
+				tokens = if this.p._highlight?
+					then @analyze this.p._highlight
+					else @analyze this.p.text
 
-				this.refs.text.innerHTML = this.refs.text.innerHTML.replace '<p class="dummy"></p>' if @p._highlight?
+				this.refs.text.innerHTML = this.refs.text.innerHTML.replace '<p class="dummy"></p>' if this.p._highlight?
 					then @compile tokens, true, false
 					else @compile tokens
 
-				this.refs.text.children.for-each (e) =>
+				this.refs.text.children.forEach (e) =>
 					if e.tag-name == 'MK-URL' 
 						riot.mount e
 
@@ -316,32 +316,32 @@
 					.filter (t) -> t.type == 'link' 
 					.map (t) =>
 						this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-						riot.mount @preview, do
+						riot.mount this.preview, do
 							url: t.content
 
 		this.reply = () => {
 			@open-post-form do
-				reply: @p
+				reply: this.p
 
 		this.repost = () => {
 			text = window.prompt '「' + @summary + '」をRepost'
 			if text?
 				this.api 'posts/create' do
-					repost_id: @p.id
+					repost_id: this.p.id
 					text: if text == '' then undefined else text
 
 		this.like = () => {
-			if @p.is_liked
+			if this.p.is_liked
 				this.api 'posts/likes/delete' do
-					post_id: @p.id
+					post_id: this.p.id
 				.then =>
-					@p.is_liked = false
+					this.p.is_liked = false
 					this.update();
 			else
 				this.api 'posts/likes/create' do
-					post_id: @p.id
+					post_id: this.p.id
 				.then =>
-					@p.is_liked = true
+					this.p.is_liked = true
 					this.update();
 	</script>
 </mk-timeline-post>
diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag
index c6ae41455..3887045e8 100644
--- a/src/web/app/mobile/tags/timeline.tag
+++ b/src/web/app/mobile/tags/timeline.tag
@@ -85,34 +85,34 @@
 				@set-posts posts
 
 		this.on('update', () => {
-			@posts.for-each (post) =>
-				date = (new Date post.created_at).get-date!
-				month = (new Date post.created_at).get-month! + 1
+			this.posts.forEach (post) =>
+				date = (new Date post.created_at).getDate()
+				month = (new Date post.created_at).getMonth() + 1
 				post._date = date
 				post._datetext = month + '月 ' + date + '日'
 
 		this.more = () => {
-			if @init or @fetching or @posts.length == 0 then return
+			if @init or @fetching or this.posts.length == 0 then return
 			this.fetching = true
 			this.update();
 			this.opts.more!.then (posts) =>
 				this.fetching = false
-				@prepend-posts posts
+				this.prepend-posts posts
 
 		this.set-posts = (posts) => {
 			this.posts = posts
 			this.update();
 
 		this.prepend-posts = (posts) => {
-			posts.for-each (post) =>
-				@posts.push post
+			posts.forEach (post) =>
+				this.posts.push post
 				this.update();
 
 		this.add-post = (post) => {
-			@posts.unshift post
+			this.posts.unshift post
 			this.update();
 
 		this.tail = () => {
-			@posts[@posts.length - 1]
+			this.posts[this.posts.length - 1]
 	</script>
 </mk-timeline>
diff --git a/src/web/app/mobile/tags/ui-nav.tag b/src/web/app/mobile/tags/ui-nav.tag
index 67fbeefd1..d8769d9c0 100644
--- a/src/web/app/mobile/tags/ui-nav.tag
+++ b/src/web/app/mobile/tags/ui-nav.tag
@@ -126,6 +126,6 @@
 		this.search = () => {
 			query = window.prompt '検索' 
 			if query? and query != ''
-				@page '/search:' + query
+				this.page '/search:' + query
 	</script>
 </mk-ui-nav>
diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag
index 3913de754..348c88b77 100644
--- a/src/web/app/mobile/tags/ui.tag
+++ b/src/web/app/mobile/tags/ui.tag
@@ -23,11 +23,11 @@
 		// alert text
 
 		this.on('mount', () => {
-			@stream.on 'notification' this.on-stream-notification
+			this.stream.on 'notification' this.on-stream-notification
 			@ready!
 
 		this.on('unmount', () => {
-			@stream.off 'notification' this.on-stream-notification
+			this.stream.off 'notification' this.on-stream-notification
 
 		this.ready = () => {
 			@ready-count++
diff --git a/src/web/app/mobile/tags/users-list.tag b/src/web/app/mobile/tags/users-list.tag
index b0f7f73ff..fc582e266 100644
--- a/src/web/app/mobile/tags/users-list.tag
+++ b/src/web/app/mobile/tags/users-list.tag
@@ -86,7 +86,7 @@
 			this.fetching = true
 			this.update();
 			obj <~ this.opts.fetch do
-				@mode == 'iknow' 
+				this.mode == 'iknow' 
 				@limit
 				null
 			this.users = obj.users
@@ -99,7 +99,7 @@
 			this.more-fetching = true
 			this.update();
 			obj <~ this.opts.fetch do
-				@mode == 'iknow' 
+				this.mode == 'iknow' 
 				@limit
 				@cursor
 			this.users = @users.concat obj.users

From 3211d90e09857210376f213bd3365b2e4c6040af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?syuilo=E2=AD=90=EF=B8=8F?= <Syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 11:31:18 +0900
Subject: [PATCH 07/32] Update room.tag

---
 src/web/app/common/tags/messaging/room.tag | 101 ++++++++++++---------
 1 file changed, 57 insertions(+), 44 deletions(-)

diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index 6565d4c41..f8088470e 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -139,70 +139,82 @@
 			this.connection.event.on('message' this.onMessage);
 			this.connection.event.on('read' this.onRead);
 
-			document.addEventListener 'visibilitychange' this.on-visibilitychange
+			document.addEventListener('visibilitychange', this.onVisibilitychange);
 
-			this.api 'messaging/messages' do
-				user_id: @user.id
-			.then (messages) =>
-				this.init = false
-				this.messages = messages.reverse!
+			this.api('messaging/messages', {
+				user_id: this.user.id
+			}).then(messages => {
+				this.init = false;
+				this.messages = messages.reverse();
 				this.update();
-				@scroll-to-bottom!
-			.catch (err) =>
-				console.error err
+				this.scrollToBottom();
+			});
+		});
 
 		this.on('unmount', () => {
-			@connection.event.off 'message' this.on-message
-			@connection.event.off 'read' this.on-read
-			@connection.close!
+			this.connection.event.off('message', this.onMessage);
+			this.connection.event.off('read', this.onRead);
+			this.connection.close();
 
-			document.removeEventListener 'visibilitychange' this.on-visibilitychange
+			document.removeEventListener('visibilitychange', this.onVisibilitychange);
+		});
 
 		this.on('update', () => {
-			@messages.forEach (message) =>
-				date = (new Date message.created_at).getDate()
-				month = (new Date message.created_at).getMonth() + 1
-				message._date = date
-				message._datetext = month + '月 ' + date + '日'
+			this.messages.forEach(message => {
+				const date = (new Date(message.created_at)).getDate();
+				const month = (new Date(message.created_at)).getMonth() + 1;
+				message._date = date;
+				message._datetext = month + '月 ' + date + '日';
+			});
+		});
 
-		this.on-message = (message) => {
-			is-bottom = @is-bottom!
+		this.onMessage = (message) => {
+			const isbottom = this.isBottom();
 
-			@messages.push message
-			if message.user_id != this.I.id and not document.hidden
-				@connection.socket.send JSON.stringify do
-					type: 'read' 
+			this.messages.push(message);
+			if (message.user_id != this.I.id && !document.hidden) {
+				this.connection.socket.send(JSON.stringify({
+					type: 'read',
 					id: message.id
+				});
+			}
 			this.update();
 
-			if is-bottom
+			if (isBottom) {
 				// Scroll to bottom
-				@scroll-to-bottom!
-			else if message.user_id != this.I.id
+				this.scrollToBottom();
+			} else if (message.user_id != this.I.id) {
 				// Notify
-				@notify '新しいメッセージがあります'
+				this.notify('新しいメッセージがあります');
+			}
+		};
 
-		this.on-read = (ids) => {
-			if not Array.isArray ids then ids = [ids]
-			ids.forEach (id) =>
-				if (@messages.some (x) => x.id == id)
-					exist = (@messages.map (x) -> x.id).index-of id
-					@messages[exist].is_read = true
+		this.onRead = ids => {
+			if (!Array.isArray(ids)) ids = [ids];
+			ids.forEach(id => {
+				if (this.messages.some(x => x.id == id)) {
+					const exist = this.messages.map(x => x.id).indexOf(id);
+					this.messages[exist].is_read = true;
 					this.update();
+				}
+			}):
+		};
 
-		this.is-bottom = () => {
-			current = this.root.scroll-top + this.root.offset-height
-			max = this.root.scroll-height
-			current > (max - 32)
+		this.isBottom = () => {
+			const current = this.root.scrollTop + this.root.offsetHeight;
+			const max = this.root.scrollHeight;
+			return current > (max - 32);
+		};
 
 		this.scroll-to-bottom = () => {
-			this.root.scroll-top = this.root.scroll-height
+			this.root.scrollTop = this.root.scrollHeight;
+		};
 
-		this.notify = (message) => {
-			n = document.createElement 'p' 
-			n.inner-HTML = '<i class="fa fa-arrow-circle-down"></i>' + message
-			n.onclick = =>
-				@scroll-to-bottom!
+		this.notify = message => {
+			const n = document.createElement('p');
+			n.innerHTML = '<i class="fa fa-arrow-circle-down"></i>' + message;
+			n.onclick = () => {
+				this.scrollToBottom();
 				n.parentNode.removeChild n
 			this.refs.notifications.appendChild n
 
@@ -212,6 +224,7 @@
 					n.parentNode.removeChild n
 				, 1000ms
 			, 4000ms
+		};
 
 		this.on-visibilitychange = () => {
 			if document.hidden then return

From 12cba7a76d368c21468c1dd4ddb0b5b164e1d9ae Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 14:33:30 +0900
Subject: [PATCH 08/32] wip

---
 src/web/app/auth/tags/index.tag               |  2 +-
 .../desktop/tags/autocomplete-suggestion.tag  |  6 +--
 .../app/desktop/tags/big-follow-button.tag    | 16 ++++----
 src/web/app/desktop/tags/contextmenu.tag      |  8 ++--
 src/web/app/desktop/tags/dialog.tag           | 26 ++++++------
 src/web/app/desktop/tags/follow-button.tag    | 16 ++++----
 .../app/desktop/tags/following-setuper.tag    |  2 +-
 .../desktop/tags/home-widgets/mentions.tag    |  2 +-
 .../desktop/tags/home-widgets/timeline.tag    |  2 +-
 .../app/desktop/tags/home-widgets/tips.tag    |  8 ++--
 .../tags/home-widgets/user-recommendation.tag |  4 +-
 src/web/app/desktop/tags/image-dialog.tag     | 16 ++++----
 src/web/app/desktop/tags/search-posts.tag     |  2 +-
 src/web/app/desktop/tags/stream-indicator.tag | 12 +++---
 src/web/app/desktop/tags/ui-notification.tag  | 26 ++++++------
 src/web/app/desktop/tags/user-followers.tag   | 15 +++----
 src/web/app/desktop/tags/user-following.tag   | 15 +++----
 .../app/desktop/tags/user-friends-graph.tag   |  6 +--
 src/web/app/desktop/tags/user-graphs.tag      |  1 +
 src/web/app/desktop/tags/user-header.tag      | 41 ++++++++++---------
 src/web/app/desktop/tags/user-likes-graph.tag |  4 +-
 src/web/app/desktop/tags/user-photos.tag      |  4 +-
 src/web/app/desktop/tags/user-posts-graph.tag |  4 +-
 src/web/app/desktop/tags/user-preview.tag     | 12 +++---
 src/web/app/desktop/tags/user-profile.tag     |  4 +-
 src/web/app/desktop/tags/user-timeline.tag    |  8 ++--
 src/web/app/desktop/tags/user.tag             |  2 +-
 src/web/app/desktop/tags/users-list.tag       |  2 +-
 src/web/app/desktop/tags/window.tag           | 26 ++++++------
 src/web/app/mobile/tags/follow-button.tag     | 16 ++++----
 src/web/app/mobile/tags/notify.tag            |  8 ++--
 src/web/app/mobile/tags/stream-indicator.tag  | 12 +++---
 src/web/app/mobile/tags/user-followers.tag    |  2 +-
 src/web/app/mobile/tags/user-following.tag    |  2 +-
 src/web/app/mobile/tags/user-timeline.tag     |  4 +-
 src/web/app/mobile/tags/user.tag              |  2 +-
 src/web/app/mobile/tags/users-list.tag        |  2 +-
 37 files changed, 173 insertions(+), 167 deletions(-)

diff --git a/src/web/app/auth/tags/index.tag b/src/web/app/auth/tags/index.tag
index 0059fef20..e64fedb26 100644
--- a/src/web/app/auth/tags/index.tag
+++ b/src/web/app/auth/tags/index.tag
@@ -97,7 +97,7 @@
 		this.token = window.location.href.split '/' .pop!
 
 		this.on('mount', () => {
-			if not @SIGNIN then return
+			if not this.SIGNIN then return
 
 			// Fetch session
 			this.api 'auth/session/show' do
diff --git a/src/web/app/desktop/tags/autocomplete-suggestion.tag b/src/web/app/desktop/tags/autocomplete-suggestion.tag
index 126c3f3be..29212fb05 100644
--- a/src/web/app/desktop/tags/autocomplete-suggestion.tag
+++ b/src/web/app/desktop/tags/autocomplete-suggestion.tag
@@ -126,7 +126,7 @@
 					if @select != -1
 						e.preventDefault();
 						e.stopPropagation();
-						@complete @users[@select]
+						@complete this.users[@select]
 					else
 						@close!
 				| 27 => // Key[ESC]
@@ -150,7 +150,7 @@
 		this.select-next = () => {
 			@select++
 
-			if @select >= @users.length
+			if @select >= this.users.length
 				this.select = 0
 
 			@apply-select!
@@ -159,7 +159,7 @@
 			@select--
 
 			if @select < 0
-				this.select = @users.length - 1
+				this.select = this.users.length - 1
 
 			@apply-select!
 
diff --git a/src/web/app/desktop/tags/big-follow-button.tag b/src/web/app/desktop/tags/big-follow-button.tag
index e4200277c..f8676669f 100644
--- a/src/web/app/desktop/tags/big-follow-button.tag
+++ b/src/web/app/desktop/tags/big-follow-button.tag
@@ -80,7 +80,7 @@
 		this.wait = false
 
 		this.on('mount', () => {
-			@user-promise.then (user) =>
+			this.user-promise.then (user) =>
 				this.user = user
 				this.init = false
 				this.update();
@@ -92,22 +92,22 @@
 			this.stream.off 'unfollow' this.on-stream-unfollow
 
 		this.on-stream-follow = (user) => {
-			if user.id == @user.id
+			if user.id == this.user.id
 				this.user = user
 				this.update();
 
 		this.on-stream-unfollow = (user) => {
-			if user.id == @user.id
+			if user.id == this.user.id
 				this.user = user
 				this.update();
 
 		this.onclick = () => {
 			this.wait = true
-			if @user.is_following
+			if this.user.is_following
 				this.api 'following/delete' do
-					user_id: @user.id
+					user_id: this.user.id
 				.then =>
-					@user.is_following = false
+					this.user.is_following = false
 				.catch (err) ->
 					console.error err
 				.then =>
@@ -115,9 +115,9 @@
 					this.update();
 			else
 				this.api 'following/create' do
-					user_id: @user.id
+					user_id: this.user.id
 				.then =>
-					@user.is_following = true
+					this.user.is_following = true
 				.catch (err) ->
 					console.error err
 				.then =>
diff --git a/src/web/app/desktop/tags/contextmenu.tag b/src/web/app/desktop/tags/contextmenu.tag
index 87dde8a84..a16e7d2d0 100644
--- a/src/web/app/desktop/tags/contextmenu.tag
+++ b/src/web/app/desktop/tags/contextmenu.tag
@@ -111,11 +111,11 @@
 			this.root.style.left = pos.x + 'px' 
 			this.root.style.top = pos.y + 'px' 
 
-			Velocity this.root, 'finish' true
-			Velocity this.root, { opacity: 0 } 0ms
-			Velocity this.root, {
+			Velocity(this.root, 'finish' true
+			Velocity(this.root, { opacity: 0 } 0ms
+			Velocity(this.root, {
 				opacity: 1
-			} {
+			}, {
 				queue: false
 				duration: 100ms
 				easing: 'linear' 
diff --git a/src/web/app/desktop/tags/dialog.tag b/src/web/app/desktop/tags/dialog.tag
index d4088fabd..affa2a88d 100644
--- a/src/web/app/desktop/tags/dialog.tag
+++ b/src/web/app/desktop/tags/dialog.tag
@@ -91,46 +91,46 @@
 			this.refs.body.innerHTML = this.opts.text
 
 			this.refs.bg.style.pointer-events = 'auto' 
-			Velocity this.refs.bg, 'finish' true
-			Velocity this.refs.bg, {
+			Velocity(this.refs.bg, 'finish' true
+			Velocity(this.refs.bg, {
 				opacity: 1
-			} {
+			}, {
 				queue: false
 				duration: 100ms
 				easing: 'linear' 
 			}
 
-			Velocity this.refs.main, {
+			Velocity(this.refs.main, {
 				opacity: 0
 				scale: 1.2
-			} {
+			}, {
 				duration: 0
 			}
-			Velocity this.refs.main, {
+			Velocity(this.refs.main, {
 				opacity: 1
 				scale: 1
-			} {
+			}, {
 				duration: 300ms
 				easing: [ 0, 0.5, 0.5, 1 ]
 			}
 
 		this.close = () => {
 			this.refs.bg.style.pointer-events = 'none' 
-			Velocity this.refs.bg, 'finish' true
-			Velocity this.refs.bg, {
+			Velocity(this.refs.bg, 'finish' true
+			Velocity(this.refs.bg, {
 				opacity: 0
-			} {
+			}, {
 				queue: false
 				duration: 300ms
 				easing: 'linear' 
 			}
 
 			this.refs.main.style.pointer-events = 'none' 
-			Velocity this.refs.main, 'finish' true
-			Velocity this.refs.main, {
+			Velocity(this.refs.main, 'finish' true
+			Velocity(this.refs.main, {
 				opacity: 0
 				scale: 0.8
-			} {
+			}, {
 				queue: false
 				duration: 300ms
 				easing: [ 0.5, -0.5, 1, 0.5 ]
diff --git a/src/web/app/desktop/tags/follow-button.tag b/src/web/app/desktop/tags/follow-button.tag
index 7b4f8f81d..09ef98422 100644
--- a/src/web/app/desktop/tags/follow-button.tag
+++ b/src/web/app/desktop/tags/follow-button.tag
@@ -77,7 +77,7 @@
 		this.wait = false
 
 		this.on('mount', () => {
-			@user-promise.then (user) =>
+			this.user-promise.then (user) =>
 				this.user = user
 				this.init = false
 				this.update();
@@ -89,22 +89,22 @@
 			this.stream.off 'unfollow' this.on-stream-unfollow
 
 		this.on-stream-follow = (user) => {
-			if user.id == @user.id
+			if user.id == this.user.id
 				this.user = user
 				this.update();
 
 		this.on-stream-unfollow = (user) => {
-			if user.id == @user.id
+			if user.id == this.user.id
 				this.user = user
 				this.update();
 
 		this.onclick = () => {
 			this.wait = true
-			if @user.is_following
+			if this.user.is_following
 				this.api 'following/delete' do
-					user_id: @user.id
+					user_id: this.user.id
 				.then =>
-					@user.is_following = false
+					this.user.is_following = false
 				.catch (err) ->
 					console.error err
 				.then =>
@@ -112,9 +112,9 @@
 					this.update();
 			else
 				this.api 'following/create' do
-					user_id: @user.id
+					user_id: this.user.id
 				.then =>
-					@user.is_following = true
+					this.user.is_following = true
 				.catch (err) ->
 					console.error err
 				.then =>
diff --git a/src/web/app/desktop/tags/following-setuper.tag b/src/web/app/desktop/tags/following-setuper.tag
index fa540511a..c4adfbd86 100644
--- a/src/web/app/desktop/tags/following-setuper.tag
+++ b/src/web/app/desktop/tags/following-setuper.tag
@@ -151,7 +151,7 @@
 				console.error err
 
 		this.refresh = () => {
-			if @users.length < @limit
+			if this.users.length < @limit
 				this.page = 0
 			else
 				this.page++
diff --git a/src/web/app/desktop/tags/home-widgets/mentions.tag b/src/web/app/desktop/tags/home-widgets/mentions.tag
index 706242547..d3f9eac3a 100644
--- a/src/web/app/desktop/tags/home-widgets/mentions.tag
+++ b/src/web/app/desktop/tags/home-widgets/mentions.tag
@@ -100,7 +100,7 @@
 				console.error err
 
 		this.on-scroll = () => {
-			current = window.scroll-y + window.inner-height
+			current = window.scrollY + window.inner-height
 			if current > document.body.offset-height - 8
 				@more!
 
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index b04068956..6e3e867e5 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -104,7 +104,7 @@
 			@load!
 
 		this.on-scroll = () => {
-			current = window.scroll-y + window.inner-height
+			current = window.scrollY + window.inner-height
 			if current > document.body.offset-height - 8
 				@more!
 	</script>
diff --git a/src/web/app/desktop/tags/home-widgets/tips.tag b/src/web/app/desktop/tags/home-widgets/tips.tag
index 6718c7063..ff7516f33 100644
--- a/src/web/app/desktop/tags/home-widgets/tips.tag
+++ b/src/web/app/desktop/tags/home-widgets/tips.tag
@@ -53,17 +53,17 @@
 			this.update();
 
 		this.change = () => {
-			Velocity this.refs.tip, {
+			Velocity(this.refs.tip, {
 				opacity: 0
-			} {
+			}, {
 				duration: 500ms
 				easing: 'linear' 
 				complete: @set
 			}
 
-			Velocity this.refs.tip, {
+			Velocity(this.refs.tip, {
 				opacity: 1
-			} {
+			}, {
 				duration: 500ms
 				easing: 'linear' 
 			}
diff --git a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
index 19b6310ea..64c9c04e9 100644
--- a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
+++ b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
@@ -121,7 +121,7 @@
 		this.on('mount', () => {
 			@fetch!
 			this.clock = setInterval =>
-				if @users.length < @limit
+				if this.users.length < @limit
 					@fetch true
 			, 60000ms
 
@@ -143,7 +143,7 @@
 				console.error err
 
 		this.refresh = () => {
-			if @users.length < @limit
+			if this.users.length < @limit
 				this.page = 0
 			else
 				this.page++
diff --git a/src/web/app/desktop/tags/image-dialog.tag b/src/web/app/desktop/tags/image-dialog.tag
index 9a8a0e3b7..a1acd05f6 100644
--- a/src/web/app/desktop/tags/image-dialog.tag
+++ b/src/web/app/desktop/tags/image-dialog.tag
@@ -38,34 +38,34 @@
 		this.image = this.opts.image
 
 		this.on('mount', () => {
-			Velocity this.root, {
+			Velocity(this.root, {
 				opacity: 1
-			} {
+			}, {
 				duration: 100ms
 				easing: 'linear' 
 			}
 
-			#Velocity @img, {
+			#Velocity(@img, {
 			// scale: 1
 			// opacity: 1
-			#} {
+			#}, {
 			// duration: 200ms
 			// easing: 'ease-out' 
 			#}
 
 		this.close = () => {
-			Velocity this.root, {
+			Velocity(this.root, {
 				opacity: 0
-			} {
+			}, {
 				duration: 100ms
 				easing: 'linear' 
 				complete: => this.unmount();
 			}
 
-			#Velocity @img, {
+			#Velocity(@img, {
 			// scale: 0.9
 			// opacity: 0
-			#} {
+			#}, {
 			// duration: 200ms
 			// easing: 'ease-in' 
 			// complete: =>
diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag
index c56caa05e..dd3b8e66e 100644
--- a/src/web/app/desktop/tags/search-posts.tag
+++ b/src/web/app/desktop/tags/search-posts.tag
@@ -79,7 +79,7 @@
 				console.error err
 
 		this.on-scroll = () => {
-			current = window.scroll-y + window.inner-height
+			current = window.scrollY + window.inner-height
 			if current > document.body.offset-height - 16 // 遊び
 				@more!
 	</script>
diff --git a/src/web/app/desktop/tags/stream-indicator.tag b/src/web/app/desktop/tags/stream-indicator.tag
index c3669c074..9ca311c47 100644
--- a/src/web/app/desktop/tags/stream-indicator.tag
+++ b/src/web/app/desktop/tags/stream-indicator.tag
@@ -30,24 +30,24 @@
 		this.mixin('stream');
 
 		this.on('before-mount', () => {
-			this.state = @get-stream-state!
+			this.state = this.getStreamState();
 
-			if @state == 'connected' 
+			if this.state == 'connected' 
 				this.root.style.opacity = 0
 
 		this.stream-state-ev.on('connected', () => {
-			this.state = @get-stream-state!
+			this.state = this.getStreamState();
 			this.update();
 			setTimeout =>
-				Velocity this.root, {
+				Velocity(this.root, {
 					opacity: 0
 				} 200ms 'linear' 
 			, 1000ms
 
 		this.stream-state-ev.on('closed', () => {
-			this.state = @get-stream-state!
+			this.state = this.getStreamState();
 			this.update();
-			Velocity this.root, {
+			Velocity(this.root, {
 				opacity: 1
 			} 0ms
 	</script>
diff --git a/src/web/app/desktop/tags/ui-notification.tag b/src/web/app/desktop/tags/ui-notification.tag
index 22ba98df9..34f310844 100644
--- a/src/web/app/desktop/tags/ui-notification.tag
+++ b/src/web/app/desktop/tags/ui-notification.tag
@@ -23,22 +23,22 @@
 	</style>
 	<script>
 		this.on('mount', () => {
-			Velocity this.root, {
+			Velocity(this.root, {
 				top: '0px' 
-			} {
-				duration: 500ms
+			}, {
+				duration: 500,
 				easing: 'ease-out' 
-			}
+			})
 
-			setTimeout =>
-				Velocity this.root, {
+			setTimeout(() => {
+				Velocity(this.root, {
 					top: '-64px' 
-				} {
-					duration: 500ms
-					easing: 'ease-out' 
-					complete: =>
-						this.unmount();
-				}
-			, 6000ms
+				}, {
+					duration: 500,
+					easing: 'ease-out',
+					complete: () => this.unmount()
+				});
+			}, 6000);
+		});
 	</script>
 </mk-ui-notification>
diff --git a/src/web/app/desktop/tags/user-followers.tag b/src/web/app/desktop/tags/user-followers.tag
index 53c3c8985..f43e87de8 100644
--- a/src/web/app/desktop/tags/user-followers.tag
+++ b/src/web/app/desktop/tags/user-followers.tag
@@ -9,14 +9,15 @@
 	<script>
 		this.mixin('api');
 
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.fetch = (iknow, limit, cursor, cb) => {
-			this.api 'users/followers' do
-				user_id: @user.id
-				iknow: iknow
-				limit: limit
-				cursor: if cursor? then cursor else undefined
-			.then cb
+			this.api('users/followers', {
+				user_id: this.user.id,
+				iknow: iknow,
+				limit: limit,
+				cursor: cursor ? cursor : undefined
+			}).then(cb);
+		};
 	</script>
 </mk-user-followers>
diff --git a/src/web/app/desktop/tags/user-following.tag b/src/web/app/desktop/tags/user-following.tag
index a8f9ccb89..f2d21b3fe 100644
--- a/src/web/app/desktop/tags/user-following.tag
+++ b/src/web/app/desktop/tags/user-following.tag
@@ -9,14 +9,15 @@
 	<script>
 		this.mixin('api');
 
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.fetch = (iknow, limit, cursor, cb) => {
-			this.api 'users/following' do
-				user_id: @user.id
-				iknow: iknow
-				limit: limit
-				cursor: if cursor? then cursor else undefined
-			.then cb
+			this.api('users/following', {
+				user_id: this.user.id,
+				iknow: iknow,
+				limit: limit,
+				cursor: cursor ? cursor : undefined
+			}).then(cb);
+		};
 	</script>
 </mk-user-following>
diff --git a/src/web/app/desktop/tags/user-friends-graph.tag b/src/web/app/desktop/tags/user-friends-graph.tag
index 923ea6fe9..76827fbda 100644
--- a/src/web/app/desktop/tags/user-friends-graph.tag
+++ b/src/web/app/desktop/tags/user-friends-graph.tag
@@ -15,18 +15,18 @@
 		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
 		this.on('mount', () => {
-			user <~ @user-promise.then
+			user <~ this.user-promise.then
 			this.user = user
 			this.update();
 
 			this.api 'aggregation/users/followers' do
-				user_id: @user.id
+				user_id: this.user.id
 				limit: 30days
 			.then (followers) =>
 				followers = followers.reverse!
 
 				this.api 'aggregation/users/following' do
-					user_id: @user.id
+					user_id: this.user.id
 					limit: 30days
 				.then (following) =>
 					following = following.reverse!
diff --git a/src/web/app/desktop/tags/user-graphs.tag b/src/web/app/desktop/tags/user-graphs.tag
index ad1c4d7ee..e673f7700 100644
--- a/src/web/app/desktop/tags/user-graphs.tag
+++ b/src/web/app/desktop/tags/user-graphs.tag
@@ -36,5 +36,6 @@
 	<script>
 		this.on('mount', () => {
 			this.trigger('loaded');
+		});
 	</script>
 </mk-user-graphs>
diff --git a/src/web/app/desktop/tags/user-header.tag b/src/web/app/desktop/tags/user-header.tag
index ff37b334e..c26535716 100644
--- a/src/web/app/desktop/tags/user-header.tag
+++ b/src/web/app/desktop/tags/user-header.tag
@@ -108,35 +108,38 @@
 		this.mixin('update-banner');
 		this.mixin('NotImplementedException');
 
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.on('mount', () => {
-			window.addEventListener 'load' @scroll
-			window.addEventListener 'scroll' @scroll
-			window.addEventListener 'resize' @scroll
+			window.addEventListener('load', this.scroll);
+			window.addEventListener('scroll', this.scroll);
+			window.addEventListener('resize', this.scroll);
+		});
 
 		this.on('unmount', () => {
-			window.removeEventListener 'load' @scroll
-			window.removeEventListener 'scroll' @scroll
-			window.removeEventListener 'resize' @scroll
+			window.removeEventListener('load', this.scroll);
+			window.removeEventListener('scroll', this.scroll);
+			window.removeEventListener('resize', this.scroll);
+		});
 
 		this.scroll = () => {
-			top = window.scroll-y
-			height = 280px
+			const top = window.scrollY;
+			const height = 280/*px*/;
 
-			pos = 50 - ((top / height) * 50)
-			this.refs.banner.style.background-position = 'center ' + pos + '%'
+			const pos = 50 - ((top / height) * 50);
+			this.refs.banner.style.backgroundPosition = `center ${pos}%`;
 
-			blur = top / 32
-			if blur <= 10
-				this.refs.banner.style.filter = 'blur(' + blur + 'px)'
+			const blur = top / 32
+			if (blur <= 10) this.refs.banner.style.filter = `blur(${blur}px)`;
+		};
 
-		this.on-update-banner = () => {
-			if not @SIGNIN or this.I.id != @user.id
-				return
+		this.onUpdateBanner = () => {
+			if (!this.SIGNIN || this.I.id != this.user.id) return;
 
-			@update-banner this.I, (i) =>
-				@user.banner_url = i.banner_url
+			this.updateBanner(this.I, i => {
+				this.user.banner_url = i.banner_url;
 				this.update();
+			});
+		};
 	</script>
 </mk-user-header>
diff --git a/src/web/app/desktop/tags/user-likes-graph.tag b/src/web/app/desktop/tags/user-likes-graph.tag
index 099040133..6030efdaf 100644
--- a/src/web/app/desktop/tags/user-likes-graph.tag
+++ b/src/web/app/desktop/tags/user-likes-graph.tag
@@ -15,12 +15,12 @@
 		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
 		this.on('mount', () => {
-			user <~ @user-promise.then
+			user <~ this.user-promise.then
 			this.user = user
 			this.update();
 
 			this.api 'aggregation/users/like' do
-				user_id: @user.id
+				user_id: this.user.id
 				limit: 30days
 			.then (likes) =>
 				likes = likes.reverse!
diff --git a/src/web/app/desktop/tags/user-photos.tag b/src/web/app/desktop/tags/user-photos.tag
index 71899c92e..58ba1b73d 100644
--- a/src/web/app/desktop/tags/user-photos.tag
+++ b/src/web/app/desktop/tags/user-photos.tag
@@ -67,12 +67,12 @@
 		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
 		this.on('mount', () => {
-			@user-promise.then (user) =>
+			this.user-promise.then (user) =>
 				this.user = user
 				this.update();
 
 				this.api 'users/posts' do
-					user_id: @user.id
+					user_id: this.user.id
 					with_media: true
 					limit: 9posts
 				.then (posts) =>
diff --git a/src/web/app/desktop/tags/user-posts-graph.tag b/src/web/app/desktop/tags/user-posts-graph.tag
index 0efc61310..0be3abb4e 100644
--- a/src/web/app/desktop/tags/user-posts-graph.tag
+++ b/src/web/app/desktop/tags/user-posts-graph.tag
@@ -15,12 +15,12 @@
 		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
 		this.on('mount', () => {
-			user <~ @user-promise.then
+			user <~ this.user-promise.then
 			this.user = user
 			this.update();
 
 			this.api 'aggregation/users/post' do
-				user_id: @user.id
+				user_id: this.user.id
 				limit: 30days
 			.then (data) =>
 				data = data.reverse!
diff --git a/src/web/app/desktop/tags/user-preview.tag b/src/web/app/desktop/tags/user-preview.tag
index 00da1d8f1..6d4f0b2b0 100644
--- a/src/web/app/desktop/tags/user-preview.tag
+++ b/src/web/app/desktop/tags/user-preview.tag
@@ -114,27 +114,27 @@
 				Promise.resolve @u
 
 		this.on('mount', () => {
-			@user-promise.then (user) =>
+			this.user-promise.then (user) =>
 				this.user = user
 				this.update();
 
-			Velocity this.root, {
+			Velocity(this.root, {
 				opacity: 0
 				'margin-top': '-8px' 
 			} 0ms
-			Velocity this.root, {
+			Velocity(this.root, {
 				opacity: 1
 				'margin-top': 0
-			} {
+			}, {
 				duration: 200ms
 				easing: 'ease-out' 
 			}
 
 		this.close = () => {
-			Velocity this.root, {
+			Velocity(this.root, {
 				opacity: 0
 				'margin-top': '-8px' 
-			} {
+			}, {
 				duration: 200ms
 				easing: 'ease-out' 
 				complete: => this.unmount();
diff --git a/src/web/app/desktop/tags/user-profile.tag b/src/web/app/desktop/tags/user-profile.tag
index b613aa968..8df631ade 100644
--- a/src/web/app/desktop/tags/user-profile.tag
+++ b/src/web/app/desktop/tags/user-profile.tag
@@ -89,11 +89,11 @@
 		this.show-following = () => {
 			window = document.body.appendChild document.createElement 'mk-user-following-window' 
 			riot.mount window, do
-				user: @user
+				user: this.user
 
 		this.show-followers = () => {
 			window = document.body.appendChild document.createElement 'mk-user-followers-window' 
 			riot.mount window, do
-				user: @user
+				user: this.user
 	</script>
 </mk-user-profile>
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index c982a68a7..405097e06 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -63,7 +63,7 @@
 			document.addEventListener 'keydown' this.on-document-keydown
 			window.addEventListener 'scroll' this.on-scroll
 
-			@user-promise.then (user) =>
+			this.user-promise.then (user) =>
 				this.user = user
 				this.update();
 
@@ -83,7 +83,7 @@
 
 		this.fetch = (cb) => {
 			this.api 'users/posts' do
-				user_id: @user.id
+				user_id: this.user.id
 				with_replies: this.mode == 'with-replies' 
 			.then (posts) =>
 				this.is-loading = false
@@ -101,7 +101,7 @@
 			this.more-loading = true
 			this.update();
 			this.api 'users/posts' do
-				user_id: @user.id
+				user_id: this.user.id
 				with_replies: this.mode == 'with-replies' 
 				max_id: this.refs.timeline.tail!.id
 			.then (posts) =>
@@ -126,7 +126,7 @@
 				document.title = 'Misskey'
 
 		this.on-scroll = () => {
-			current = window.scroll-y + window.inner-height
+			current = window.scrollY + window.inner-height
 			if current > document.body.offset-height - 16 // 遊び
 				@more!
 
diff --git a/src/web/app/desktop/tags/user.tag b/src/web/app/desktop/tags/user.tag
index 8e151c831..a088d97db 100644
--- a/src/web/app/desktop/tags/user.tag
+++ b/src/web/app/desktop/tags/user.tag
@@ -41,7 +41,7 @@
 
 		this.on('mount', () => {
 			this.api 'users/show' do
-				username: @username
+				username: this.username
 			.then (user) =>
 				this.fetching = false
 				this.user = user
diff --git a/src/web/app/desktop/tags/users-list.tag b/src/web/app/desktop/tags/users-list.tag
index dbb7069c4..2d85cd2ec 100644
--- a/src/web/app/desktop/tags/users-list.tag
+++ b/src/web/app/desktop/tags/users-list.tag
@@ -120,7 +120,7 @@
 				this.mode == 'iknow' 
 				@limit
 				@cursor
-			this.users = @users.concat obj.users
+			this.users = this.users.concat obj.users
 			this.next = obj.next
 			this.more-fetching = false
 			this.update();
diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index 3c7cc14f7..f83ccf3f8 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -243,22 +243,22 @@
 
 			if @is-modal
 				this.refs.bg.style.pointer-events = 'auto' 
-				Velocity this.refs.bg, 'finish' true
-				Velocity this.refs.bg, {
+				Velocity(this.refs.bg, 'finish' true
+				Velocity(this.refs.bg, {
 					opacity: 1
-				} {
+				}, {
 					queue: false
 					duration: 100ms
 					easing: 'linear' 
 				}
 
 			this.refs.main.style.pointer-events = 'auto' 
-			Velocity this.refs.main, 'finish' true
-			Velocity this.refs.main, {scale: 1.1} 0ms
-			Velocity this.refs.main, {
+			Velocity(this.refs.main, 'finish' true
+			Velocity(this.refs.main, {scale: 1.1} 0ms
+			Velocity(this.refs.main, {
 				opacity: 1
 				scale: 1
-			} {
+			}, {
 				queue: false
 				duration: 200ms
 				easing: 'ease-out' 
@@ -275,21 +275,21 @@
 
 			if @is-modal
 				this.refs.bg.style.pointer-events = 'none' 
-				Velocity this.refs.bg, 'finish' true
-				Velocity this.refs.bg, {
+				Velocity(this.refs.bg, 'finish' true
+				Velocity(this.refs.bg, {
 					opacity: 0
-				} {
+				}, {
 					queue: false
 					duration: 300ms
 					easing: 'linear' 
 				}
 
 			this.refs.main.style.pointer-events = 'none' 
-			Velocity this.refs.main, 'finish' true
-			Velocity this.refs.main, {
+			Velocity(this.refs.main, 'finish' true
+			Velocity(this.refs.main, {
 				opacity: 0
 				scale: 0.8
-			} {
+			}, {
 				queue: false
 				duration: 300ms
 				easing: [ 0.5, -0.5, 1, 0.5 ]
diff --git a/src/web/app/mobile/tags/follow-button.tag b/src/web/app/mobile/tags/follow-button.tag
index 71a38254d..ff4c6586d 100644
--- a/src/web/app/mobile/tags/follow-button.tag
+++ b/src/web/app/mobile/tags/follow-button.tag
@@ -58,7 +58,7 @@
 		this.wait = false
 
 		this.on('mount', () => {
-			@user-promise.then (user) =>
+			this.user-promise.then (user) =>
 				this.user = user
 				this.init = false
 				this.update();
@@ -70,22 +70,22 @@
 			this.stream.off 'unfollow' this.on-stream-unfollow
 
 		this.on-stream-follow = (user) => {
-			if user.id == @user.id
+			if user.id == this.user.id
 				this.user = user
 				this.update();
 
 		this.on-stream-unfollow = (user) => {
-			if user.id == @user.id
+			if user.id == this.user.id
 				this.user = user
 				this.update();
 
 		this.onclick = () => {
 			this.wait = true
-			if @user.is_following
+			if this.user.is_following
 				this.api 'following/delete' do
-					user_id: @user.id
+					user_id: this.user.id
 				.then =>
-					@user.is_following = false
+					this.user.is_following = false
 				.catch (err) ->
 					console.error err
 				.then =>
@@ -93,9 +93,9 @@
 					this.update();
 			else
 				this.api 'following/create' do
-					user_id: @user.id
+					user_id: this.user.id
 				.then =>
-					@user.is_following = true
+					this.user.is_following = true
 				.catch (err) ->
 					console.error err
 				.then =>
diff --git a/src/web/app/mobile/tags/notify.tag b/src/web/app/mobile/tags/notify.tag
index 5d27860e4..3003528fe 100644
--- a/src/web/app/mobile/tags/notify.tag
+++ b/src/web/app/mobile/tags/notify.tag
@@ -17,17 +17,17 @@
 	</style>
 	<script>
 		this.on('mount', () => {
-			Velocity this.root, {
+			Velocity(this.root, {
 				bottom: '0px' 
-			} {
+			}, {
 				duration: 500ms
 				easing: 'ease-out' 
 			}
 
 			setTimeout =>
-				Velocity this.root, {
+				Velocity(this.root, {
 					bottom: '-64px' 
-				} {
+				}, {
 					duration: 500ms
 					easing: 'ease-out' 
 					complete: =>
diff --git a/src/web/app/mobile/tags/stream-indicator.tag b/src/web/app/mobile/tags/stream-indicator.tag
index c3669c074..9ca311c47 100644
--- a/src/web/app/mobile/tags/stream-indicator.tag
+++ b/src/web/app/mobile/tags/stream-indicator.tag
@@ -30,24 +30,24 @@
 		this.mixin('stream');
 
 		this.on('before-mount', () => {
-			this.state = @get-stream-state!
+			this.state = this.getStreamState();
 
-			if @state == 'connected' 
+			if this.state == 'connected' 
 				this.root.style.opacity = 0
 
 		this.stream-state-ev.on('connected', () => {
-			this.state = @get-stream-state!
+			this.state = this.getStreamState();
 			this.update();
 			setTimeout =>
-				Velocity this.root, {
+				Velocity(this.root, {
 					opacity: 0
 				} 200ms 'linear' 
 			, 1000ms
 
 		this.stream-state-ev.on('closed', () => {
-			this.state = @get-stream-state!
+			this.state = this.getStreamState();
 			this.update();
-			Velocity this.root, {
+			Velocity(this.root, {
 				opacity: 1
 			} 0ms
 	</script>
diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag
index 4eafb1ed9..cdde081dc 100644
--- a/src/web/app/mobile/tags/user-followers.tag
+++ b/src/web/app/mobile/tags/user-followers.tag
@@ -12,7 +12,7 @@
 
 		this.fetch = (iknow, limit, cursor, cb) => {
 			this.api 'users/followers' do
-				user_id: @user.id
+				user_id: this.user.id
 				iknow: iknow
 				limit: limit
 				cursor: if cursor? then cursor else undefined
diff --git a/src/web/app/mobile/tags/user-following.tag b/src/web/app/mobile/tags/user-following.tag
index 25d3c9926..37ee0ee39 100644
--- a/src/web/app/mobile/tags/user-following.tag
+++ b/src/web/app/mobile/tags/user-following.tag
@@ -12,7 +12,7 @@
 
 		this.fetch = (iknow, limit, cursor, cb) => {
 			this.api 'users/following' do
-				user_id: @user.id
+				user_id: this.user.id
 				iknow: iknow
 				limit: limit
 				cursor: if cursor? then cursor else undefined
diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag
index 82a641354..80311924f 100644
--- a/src/web/app/mobile/tags/user-timeline.tag
+++ b/src/web/app/mobile/tags/user-timeline.tag
@@ -16,7 +16,7 @@
 
 		this.init = new Promise (res, rej) =>
 			this.api 'users/posts' do
-				user_id: @user.id
+				user_id: this.user.id
 				with_media: @with-media
 			.then (posts) =>
 				res posts
@@ -24,7 +24,7 @@
 
 		this.more = () => {
 			this.api 'users/posts' do
-				user_id: @user.id
+				user_id: this.user.id
 				with_media: @with-media
 				max_id: this.refs.timeline.tail!.id
 	</script>
diff --git a/src/web/app/mobile/tags/user.tag b/src/web/app/mobile/tags/user.tag
index d36455e6e..660b08879 100644
--- a/src/web/app/mobile/tags/user.tag
+++ b/src/web/app/mobile/tags/user.tag
@@ -165,7 +165,7 @@
 
 		this.on('mount', () => {
 			this.api 'users/show' do
-				username: @username
+				username: this.username
 			.then (user) =>
 				this.fetching = false
 				this.user = user
diff --git a/src/web/app/mobile/tags/users-list.tag b/src/web/app/mobile/tags/users-list.tag
index fc582e266..ef225d5b5 100644
--- a/src/web/app/mobile/tags/users-list.tag
+++ b/src/web/app/mobile/tags/users-list.tag
@@ -102,7 +102,7 @@
 				this.mode == 'iknow' 
 				@limit
 				@cursor
-			this.users = @users.concat obj.users
+			this.users = this.users.concat obj.users
 			this.next = obj.next
 			this.more-fetching = false
 			this.update();

From 71509da6609315ab939d523d4ae957907d894785 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 14:36:01 +0900
Subject: [PATCH 09/32] wip

---
 src/web/app/desktop/tags/user-home.tag | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/web/app/desktop/tags/user-home.tag b/src/web/app/desktop/tags/user-home.tag
index db155edb1..759a57581 100644
--- a/src/web/app/desktop/tags/user-home.tag
+++ b/src/web/app/desktop/tags/user-home.tag
@@ -35,10 +35,12 @@
 
 	</style>
 	<script>
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.on('mount', () => {
 			this.refs.tl.on('loaded', () => {
 				this.trigger('loaded');
+			});
+		});
 	</script>
 </mk-user-home>

From b0c1ec31243631ec665813acff492b88538bc873 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 14:51:19 +0900
Subject: [PATCH 10/32] wip

---
 src/web/app/desktop/tags/donation.tag  |  5 ++---
 src/web/app/desktop/tags/ui-header.tag |  2 +-
 src/web/app/desktop/tags/ui.tag        | 29 +++++++++++++-------------
 3 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/src/web/app/desktop/tags/donation.tag b/src/web/app/desktop/tags/donation.tag
index 0946e430d..57b36a305 100644
--- a/src/web/app/desktop/tags/donation.tag
+++ b/src/web/app/desktop/tags/donation.tag
@@ -50,7 +50,7 @@
 		this.mixin('api');
 		this.mixin('i');
 
-		this.close = (e) => {
+		this.close = e => {
 			e.preventDefault();
 			e.stopPropagation();
 
@@ -61,7 +61,6 @@
 					no_donation: this.I.data.no_donation
 
 			this.unmount();
-
-			this.parent.parent.set-root-layout!
+		};
 	</script>
 </mk-donation>
diff --git a/src/web/app/desktop/tags/ui-header.tag b/src/web/app/desktop/tags/ui-header.tag
index 05d1ff665..9dd1ace6b 100644
--- a/src/web/app/desktop/tags/ui-header.tag
+++ b/src/web/app/desktop/tags/ui-header.tag
@@ -21,7 +21,7 @@
 	<style>
 		:scope
 			display block
-			position fixed
+			position sticky
 			top 0
 			z-index 1024
 			width 100%
diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag
index 1e2cba35b..e6781f4a2 100644
--- a/src/web/app/desktop/tags/ui.tag
+++ b/src/web/app/desktop/tags/ui.tag
@@ -9,29 +9,28 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('i');
 
-		this.open-post-form = () => {
-			riot.mount document.body.appendChild document.createElement 'mk-post-form-window' 
-
-		this.set-root-layout = () => {
-			this.root.style.padding-top = this.refs.header.root.client-height + 'px' 
+		this.openPostForm = () => {
+			riot.mount(document.body.appendChild(document.createElement('mk-post-form-window');
+		};
 
 		this.on('mount', () => {
-			@set-root-layout!
-			document.addEventListener 'keydown' this.onkeydown
+			document.addEventListener('keydown', this.onkeydown);
+		});
 
 		this.on('unmount', () => {
-			document.removeEventListener 'keydown' this.onkeydown
+			document.removeEventListener('keydown', this.onkeydown);
+		});
 
-		this.onkeydown = (e) => {
-			tag = e.target.tag-name.to-lower-case!
-			if tag != 'input' and tag != 'textarea' 
-				if e.which == 80 or e.which == 78 // p or n
-					e.preventDefault();
-					@open-post-form!
+		this.onkeydown = e => {
+			if (e.target.tagName == 'input' || e.target.tagName == 'textarea') return;
+
+			if (e.which == 80 || e.which == 78) { // p or n
+				e.preventDefault();
+				this.openPostForm();
+		};
 	</script>
 </mk-ui>

From 4c43573c1ea34602b5d41998a0fa08708808de52 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 14:55:20 +0900
Subject: [PATCH 11/32] wip

---
 src/web/app/desktop/tags/timeline-post.tag | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/web/app/desktop/tags/timeline-post.tag b/src/web/app/desktop/tags/timeline-post.tag
index 6f5841a76..0d572981c 100644
--- a/src/web/app/desktop/tags/timeline-post.tag
+++ b/src/web/app/desktop/tags/timeline-post.tag
@@ -318,14 +318,14 @@
 		this.mixin('user-preview');
 		this.mixin('NotImplementedException');
 
-		this.post = this.opts.post
-		this.is-repost = this.post.repost? and !this.post.text?
-		this.p = if @is-repost then this.post.repost else this.post
+		this.post = this.opts.post;
+		this.isRepost = this.post.repost != null && this.post.text == null;
+		this.p = this.isRepost ? this.post.repost : this.post;
 
-		this.title = @date-stringify this.p.created_at
+		this.title = this.dateStringify(this.p.created_at);
 
-		this.url = CONFIG.url + '/' + this.p.user.username + '/' + this.p.id
-		this.is-detail-opened = false
+		this.url = CONFIG.url + '/' + this.p.user.username + '/' + this.p.id;
+		this.isDetailOpened = false;
 
 		this.on('mount', () => {
 			if this.p.text?

From c05abf4da75fce296e5d744ae99e004fe1294642 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 16:09:46 +0900
Subject: [PATCH 12/32] wip

---
 src/web/app/auth/tags/form.tag                |  4 +-
 src/web/app/auth/tags/index.tag               |  6 +-
 src/web/app/common/tags/messaging/index.tag   |  4 +-
 src/web/app/common/tags/signin-history.tag    |  2 +-
 src/web/app/common/tags/signin.tag            |  6 +-
 src/web/app/common/tags/signup.tag            | 12 +--
 .../desktop/tags/autocomplete-suggestion.tag  | 16 ++--
 .../app/desktop/tags/big-follow-button.tag    |  6 +-
 src/web/app/desktop/tags/contextmenu.tag      |  2 +-
 src/web/app/desktop/tags/crop-window.tag      |  6 +-
 src/web/app/desktop/tags/dialog.tag           |  4 +-
 src/web/app/desktop/tags/donation.tag         | 10 ++-
 .../desktop/tags/drive/base-contextmenu.tag   | 10 +--
 .../app/desktop/tags/drive/browser-window.tag |  4 +-
 src/web/app/desktop/tags/drive/browser.tag    | 34 +++----
 .../desktop/tags/drive/file-contextmenu.tag   | 12 +--
 src/web/app/desktop/tags/drive/file.tag       |  4 +-
 .../desktop/tags/drive/folder-contextmenu.tag | 30 +++----
 src/web/app/desktop/tags/drive/folder.tag     |  8 +-
 src/web/app/desktop/tags/drive/nav-folder.tag |  4 +-
 src/web/app/desktop/tags/follow-button.tag    |  6 +-
 .../app/desktop/tags/following-setuper.tag    |  4 +-
 .../desktop/tags/home-widgets/mentions.tag    |  8 +-
 .../tags/home-widgets/photo-stream.tag        |  4 +-
 .../desktop/tags/home-widgets/rss-reader.tag  |  2 +-
 .../desktop/tags/home-widgets/timeline.tag    |  6 +-
 .../tags/home-widgets/user-recommendation.tag |  4 +-
 src/web/app/desktop/tags/images-viewer.tag    |  4 +-
 src/web/app/desktop/tags/input-dialog.tag     |  4 +-
 src/web/app/desktop/tags/messaging/window.tag |  4 +-
 src/web/app/desktop/tags/notifications.tag    |  2 +-
 src/web/app/desktop/tags/post-detail-sub.tag  |  4 +-
 src/web/app/desktop/tags/post-detail.tag      | 36 ++++----
 src/web/app/desktop/tags/post-form-window.tag |  2 +-
 src/web/app/desktop/tags/post-form.tag        |  8 +-
 .../app/desktop/tags/post-status-graph.tag    | 12 +--
 src/web/app/desktop/tags/progress-dialog.tag  |  2 +-
 .../app/desktop/tags/repost-form-window.tag   |  6 +-
 src/web/app/desktop/tags/repost-form.tag      |  4 +-
 src/web/app/desktop/tags/search-posts.tag     |  8 +-
 .../tags/select-file-from-drive-window.tag    |  4 +-
 src/web/app/desktop/tags/settings-window.tag  |  2 +-
 src/web/app/desktop/tags/settings.tag         | 10 +--
 src/web/app/desktop/tags/timeline-post.tag    | 50 ++++++-----
 .../app/desktop/tags/ui-header-account.tag    | 18 ++--
 src/web/app/desktop/tags/ui-header-nav.tag    |  6 +-
 .../desktop/tags/ui-header-notifications.tag  |  4 +-
 .../desktop/tags/ui-header-post-button.tag    |  5 +-
 src/web/app/desktop/tags/ui-header.tag        |  1 -
 .../app/desktop/tags/user-friends-graph.tag   |  8 +-
 src/web/app/desktop/tags/user-likes-graph.tag |  4 +-
 src/web/app/desktop/tags/user-photos.tag      |  6 +-
 src/web/app/desktop/tags/user-posts-graph.tag |  4 +-
 src/web/app/desktop/tags/user-preview.tag     |  6 +-
 src/web/app/desktop/tags/user-profile.tag     |  8 +-
 src/web/app/desktop/tags/user-timeline.tag    | 10 +--
 src/web/app/desktop/tags/user.tag             |  4 +-
 src/web/app/desktop/tags/window.tag           |  4 +-
 src/web/app/dev/tags/new-app-form.tag         | 10 +--
 src/web/app/dev/tags/pages/app.tag            |  4 +-
 src/web/app/dev/tags/pages/apps.tag           |  2 +-
 src/web/app/mobile/tags/drive.tag             | 16 ++--
 src/web/app/mobile/tags/drive/file-viewer.tag |  2 +-
 src/web/app/mobile/tags/follow-button.tag     |  6 +-
 src/web/app/mobile/tags/home-timeline.tag     |  4 +-
 src/web/app/mobile/tags/notifications.tag     |  2 +-
 .../app/mobile/tags/page/messaging-room.tag   |  4 +-
 .../app/mobile/tags/page/user-followers.tag   |  4 +-
 .../app/mobile/tags/page/user-following.tag   |  4 +-
 src/web/app/mobile/tags/post-detail.tag       | 40 ++++-----
 src/web/app/mobile/tags/post-form.tag         |  8 +-
 src/web/app/mobile/tags/search-posts.tag      |  6 +-
 src/web/app/mobile/tags/timeline-post.tag     | 89 +++++++++++--------
 src/web/app/mobile/tags/timeline.tag          |  4 +-
 src/web/app/mobile/tags/ui-header.tag         |  4 +-
 src/web/app/mobile/tags/ui.tag                |  4 +-
 src/web/app/mobile/tags/user-followers.tag    |  2 +-
 src/web/app/mobile/tags/user-following.tag    |  2 +-
 src/web/app/mobile/tags/user-timeline.tag     |  6 +-
 src/web/app/mobile/tags/user.tag              | 75 +++++++++-------
 80 files changed, 400 insertions(+), 366 deletions(-)

diff --git a/src/web/app/auth/tags/form.tag b/src/web/app/auth/tags/form.tag
index bb424d98c..21a9a7404 100644
--- a/src/web/app/auth/tags/form.tag
+++ b/src/web/app/auth/tags/form.tag
@@ -112,13 +112,13 @@
 		this.app = @session.app
 
 		this.cancel = () => {
-			this.api 'auth/deny' do
+			this.api('auth/deny', {
 				token: @session.token
 			.then =>
 				this.trigger('denied');
 
 		this.accept = () => {
-			this.api 'auth/accept' do
+			this.api('auth/accept', {
 				token: @session.token
 			.then =>
 				this.trigger('accepted');
diff --git a/src/web/app/auth/tags/index.tag b/src/web/app/auth/tags/index.tag
index e64fedb26..13abf0790 100644
--- a/src/web/app/auth/tags/index.tag
+++ b/src/web/app/auth/tags/index.tag
@@ -100,15 +100,15 @@
 			if not this.SIGNIN then return
 
 			// Fetch session
-			this.api 'auth/session/show' do
+			this.api('auth/session/show', {
 				token: @token
-			.then (session) =>
+			}).then((session) => {
 				this.session = session
 				this.fetching = false
 
 				// 既に連携していた場合
 				if @session.app.is_authorized
-					this.api 'auth/accept' do
+					this.api('auth/accept', {
 						token: @session.token
 					.then =>
 						@accepted!
diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
index ca1adaaa7..6ba6cb7d9 100644
--- a/src/web/app/common/tags/messaging/index.tag
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -310,10 +310,10 @@
 			if (q == '') {
 				this.searchResult = [];
 			} else {
-				this.api 'users/search' do
+				this.api('users/search', {
 					query: q
 					max: 5
-				.then (users) =>
+				}).then((users) => {
 					users.forEach (user) =>
 						user._click = =>
 							this.trigger 'navigate-user' user
diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag
index 6b2ca1e6c..47bf68c28 100644
--- a/src/web/app/common/tags/signin-history.tag
+++ b/src/web/app/common/tags/signin-history.tag
@@ -56,7 +56,7 @@
 
 		this.on('mount', () => {
 			this.api 'i/signin_history' 
-			.then (history) =>
+			}).then((history) => {
 				this.history = history
 				this.fetching = false
 				this.update();
diff --git a/src/web/app/common/tags/signin.tag b/src/web/app/common/tags/signin.tag
index 204ed8326..7b297b7b8 100644
--- a/src/web/app/common/tags/signin.tag
+++ b/src/web/app/common/tags/signin.tag
@@ -103,9 +103,9 @@
 		this.signing = false;
 
 		this.oninput = () => {
-			this.api 'users/show' do
+			this.api('users/show', {
 				username: this.refs.username.value
-			.then (user) =>
+			}).then((user) => {
 				this.user = user
 				this.trigger 'user' user
 				this.update();
@@ -123,7 +123,7 @@
 			this.signing = true
 			this.update();
 
-			this.api 'signin' do
+			this.api('signin', {
 				username: this.refs.username.value
 				password: this.refs.password.value
 			.then =>
diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag
index 06e044a41..7646f8c86 100644
--- a/src/web/app/common/tags/signup.tag
+++ b/src/web/app/common/tags/signup.tag
@@ -220,9 +220,9 @@
 				this.username-state = 'wait' 
 				this.update();
 
-				this.api 'username/available' do
+				this.api('username/available', {
 					username: username
-				.then (result) =>
+				}).then((result) => {
 					if result.available
 						this.username-state = 'ok' 
 					else
@@ -271,14 +271,14 @@
 			const username = this.refs.username.value;
 			const password = this.refs.password.value;
 
-			locker = document.body.appendChild document.createElement 'mk-locker' 
-
-			this.api 'signup' do
+			locker = document.body.appendChild(document.createElement('mk-locker'));
+ 
+			this.api('signup', {
 				username: username,
 				password: password,
 				'g-recaptcha-response': grecaptcha.getResponse()
 			.then =>
-				this.api 'signin' do
+				this.api('signin', {
 					username: username
 					password: password
 				.then =>
diff --git a/src/web/app/desktop/tags/autocomplete-suggestion.tag b/src/web/app/desktop/tags/autocomplete-suggestion.tag
index 29212fb05..40f5f5759 100644
--- a/src/web/app/desktop/tags/autocomplete-suggestion.tag
+++ b/src/web/app/desktop/tags/autocomplete-suggestion.tag
@@ -95,10 +95,10 @@
 			Array.prototype.forEach.call all, (el) =>
 				el.addEventListener 'mousedown' @mousedown
 
-			this.api 'users/search_by_username' do
+			this.api('users/search_by_username', {
 				query: @q
 				limit: 30users
-			.then (users) =>
+			}).then((users) => {
 				this.users = users
 				this.loading = false
 				this.update();
@@ -114,7 +114,7 @@
 
 		this.mousedown = (e) => {
 			if (!contains this.root, e.target) and (this.root != e.target)
-				@close!
+				@close();
 
 		this.on-click = (e) => {
 			@complete e.item
@@ -128,24 +128,24 @@
 						e.stopPropagation();
 						@complete this.users[@select]
 					else
-						@close!
+						@close();
 				| 27 => // Key[ESC]
 					e.preventDefault();
 					e.stopPropagation();
-					@close!
+					@close();
 				| 38 => // Key[↑]
 					if @select != -1
 						e.preventDefault();
 						e.stopPropagation();
 						@select-prev!
 					else
-						@close!
+						@close();
 				| 9, 40 => // Key[TAB] or Key[↓]
 					e.preventDefault();
 					e.stopPropagation();
 					@select-next!
 				| _ =>
-					@close!
+					@close();
 
 		this.select-next = () => {
 			@select++
@@ -174,7 +174,7 @@
 			this.opts.complete user
 
 		this.close = () => {
-			this.opts.close!
+			this.opts.close();
 
 		function contains(parent, child)
 			node = child.parentNode
diff --git a/src/web/app/desktop/tags/big-follow-button.tag b/src/web/app/desktop/tags/big-follow-button.tag
index f8676669f..ba607c837 100644
--- a/src/web/app/desktop/tags/big-follow-button.tag
+++ b/src/web/app/desktop/tags/big-follow-button.tag
@@ -80,7 +80,7 @@
 		this.wait = false
 
 		this.on('mount', () => {
-			this.user-promise.then (user) =>
+			this.user-promise}).then((user) => {
 				this.user = user
 				this.init = false
 				this.update();
@@ -104,7 +104,7 @@
 		this.onclick = () => {
 			this.wait = true
 			if this.user.is_following
-				this.api 'following/delete' do
+				this.api('following/delete', {
 					user_id: this.user.id
 				.then =>
 					this.user.is_following = false
@@ -114,7 +114,7 @@
 					this.wait = false
 					this.update();
 			else
-				this.api 'following/create' do
+				this.api('following/create', {
 					user_id: this.user.id
 				.then =>
 					this.user.is_following = true
diff --git a/src/web/app/desktop/tags/contextmenu.tag b/src/web/app/desktop/tags/contextmenu.tag
index a16e7d2d0..92c8b71a2 100644
--- a/src/web/app/desktop/tags/contextmenu.tag
+++ b/src/web/app/desktop/tags/contextmenu.tag
@@ -100,7 +100,7 @@
 		this.mousedown = (e) => {
 			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
-				@close!
+				@close();
 			return false
 
 		this.open = (pos) => {
diff --git a/src/web/app/desktop/tags/crop-window.tag b/src/web/app/desktop/tags/crop-window.tag
index 45704a4b5..56845f24a 100644
--- a/src/web/app/desktop/tags/crop-window.tag
+++ b/src/web/app/desktop/tags/crop-window.tag
@@ -175,14 +175,14 @@
 		this.ok = () => {
 			@cropper.get-cropped-canvas!.to-blob (blob) =>
 				this.trigger 'cropped' blob
-				this.refs.window.close!
+				this.refs.window.close();
 
 		this.skip = () => {
 			this.trigger('skiped');
-			this.refs.window.close!
+			this.refs.window.close();
 
 		this.cancel = () => {
 			this.trigger('canceled');
-			this.refs.window.close!
+			this.refs.window.close();
 	</script>
 </mk-crop-window>
diff --git a/src/web/app/desktop/tags/dialog.tag b/src/web/app/desktop/tags/dialog.tag
index affa2a88d..61a40e7b3 100644
--- a/src/web/app/desktop/tags/dialog.tag
+++ b/src/web/app/desktop/tags/dialog.tag
@@ -84,7 +84,7 @@
 			button._onclick = =>
 				if button.onclick?
 					button.onclick();
-				@close!
+				@close();
 
 		this.on('mount', () => {
 			this.refs.header.innerHTML = this.opts.title
@@ -142,6 +142,6 @@
 			if @can-through
 				if this.opts.on-through?
 					this.opts.on-through!
-				@close!
+				@close();
 	</script>
 </mk-dialog>
diff --git a/src/web/app/desktop/tags/donation.tag b/src/web/app/desktop/tags/donation.tag
index 57b36a305..e313188f2 100644
--- a/src/web/app/desktop/tags/donation.tag
+++ b/src/web/app/desktop/tags/donation.tag
@@ -54,11 +54,13 @@
 			e.preventDefault();
 			e.stopPropagation();
 
-			this.I.data.no_donation = true
-			this.I.update!
-			this.api 'i/appdata/set' do
-				data: JSON.stringify do
+			this.I.data.no_donation = true;
+			this.I.update();
+			this.api('i/appdata/set', {
+				data: JSON.stringify({
 					no_donation: this.I.data.no_donation
+				})
+			});
 
 			this.unmount();
 		};
diff --git a/src/web/app/desktop/tags/drive/base-contextmenu.tag b/src/web/app/desktop/tags/drive/base-contextmenu.tag
index 9503e639d..06ccba6a2 100644
--- a/src/web/app/desktop/tags/drive/base-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/base-contextmenu.tag
@@ -23,16 +23,16 @@
 		this.open = (pos) => {
 			this.refs.ctx.open pos
 
-		this.create-folder = () => {
-			this.browser.create-folder!
-			this.refs.ctx.close!
+		this.createFolder = () => {
+			this.browser.createFolder!
+			this.refs.ctx.close();
 
 		this.upload = () => {
 			this.browser.select-local-file!
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 
 		this.url-upload = () => {
 			this.browser.url-upload!
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 	</script>
 </mk-drive-browser-base-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/browser-window.tag b/src/web/app/desktop/tags/drive/browser-window.tag
index b5b2572d4..f558b3d84 100644
--- a/src/web/app/desktop/tags/drive/browser-window.tag
+++ b/src/web/app/desktop/tags/drive/browser-window.tag
@@ -36,11 +36,11 @@
 			this.refs.window.on('closed', () => {
 				this.unmount();
 
-			this.api 'drive' .then (info) =>
+			this.api 'drive' }).then((info) => {
 				@update do
 					usage: info.usage / info.capacity * 100
 
 		this.close = () => {
-			this.refs.window.close!
+			this.refs.window.close();
 	</script>
 </mk-drive-browser-window>
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index c13832523..13019dd16 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -405,7 +405,7 @@
 				if (this.files.some (f) => f.id == file)
 					return false
 				@remove-file file
-				this.api 'drive/files/update' do
+				this.api('drive/files/update', {
 					file_id: file
 					folder_id: if this.folder? then this.folder.id else null
 				.then =>
@@ -422,7 +422,7 @@
 				if (this.folders.some (f) => f.id == folder)
 					return false
 				@remove-folder folder
-				this.api 'drive/folders/update' do
+				this.api('drive/folders/update', {
 					folder_id: folder
 					parent_id: if this.folder? then this.folder.id else null
 				.then =>
@@ -442,8 +442,8 @@
 			e.preventDefault();
 			e.stopImmediatePropagation();
 
-			ctx = document.body.appendChild document.createElement 'mk-drive-browser-base-contextmenu' 
-			ctx = riot.mount ctx, do
+			ctx = document.body.appendChild(document.createElement('mk-drive-browser-base-contextmenu'));
+ 			ctx = riot.mount ctx, do
 				browser: this
 			ctx = ctx.0
 			ctx.open do
@@ -462,7 +462,7 @@
 				null
 
 			if url? and url != ''
-				this.api 'drive/files/upload_from_url' do
+				this.api('drive/files/upload_from_url', {
 					url: url
 					folder_id: if this.folder? then this.folder.id else undefined
 
@@ -473,16 +473,16 @@
 						text: 'OK' 
 					]
 
-		this.create-folder = () => {
+		this.createFolder = () => {
 			name <~ @input-dialog do
 				'フォルダー作成'
 				'フォルダー名'
 				null
 
-			this.api 'drive/folders/create' do
+			this.api('drive/folders/create', {
 				name: name
 				folder_id: if this.folder? then this.folder.id else undefined
-			.then (folder) =>
+			}).then((folder) => {
 				@add-folder folder, true
 				this.update();
 			.catch (err) =>
@@ -502,9 +502,9 @@
 		this.get-selection = () => {
 			this.files.filter (file) -> file._selected
 
-		this.new-window = (folder-id) => {
-			browser = document.body.appendChild document.createElement 'mk-drive-browser-window' 
-			riot.mount browser, do
+		this.newWindow = (folder-id) => {
+			browser = document.body.appendChild(document.createElement('mk-drive-browser-window'));
+ 			riot.mount browser, do
 				folder: folder-id
 
 		this.move = (target-folder) => {
@@ -518,9 +518,9 @@
 			this.loading = true
 			this.update();
 
-			this.api 'drive/folders/show' do
+			this.api('drive/folders/show', {
 				folder_id: target-folder
-			.then (folder) =>
+			}).then((folder) => {
 				this.folder = folder
 				this.hierarchyFolders = []
 
@@ -607,10 +607,10 @@
 			files-max = 30
 
 			// フォルダ一覧取得
-			this.api 'drive/folders' do
+			this.api('drive/folders', {
 				folder_id: if this.folder? then this.folder.id else null
 				limit: folders-max + 1
-			.then (folders) =>
+			}).then((folders) => {
 				if folders.length == folders-max + 1
 					this.more-folders = true
 					folders.pop!
@@ -620,10 +620,10 @@
 				console.error err
 
 			// ファイル一覧取得
-			this.api 'drive/files' do
+			this.api('drive/files', {
 				folder_id: if this.folder? then this.folder.id else null
 				limit: files-max + 1
-			.then (files) =>
+			}).then((files) => {
 				if files.length == files-max + 1
 					this.more-files = true
 					files.pop!
diff --git a/src/web/app/desktop/tags/drive/file-contextmenu.tag b/src/web/app/desktop/tags/drive/file-contextmenu.tag
index e8d75ccd4..9a615a902 100644
--- a/src/web/app/desktop/tags/drive/file-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/file-contextmenu.tag
@@ -58,14 +58,14 @@
 			this.refs.ctx.open pos
 
 		this.rename = () => {
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 
 			name <~ @input-dialog do
 				'ファイル名の変更'
 				'新しいファイル名を入力してください'
 				this.file.name
 
-			this.api 'drive/files/update' do
+			this.api('drive/files/update', {
 				file_id: this.file.id
 				name: name
 			.then =>
@@ -77,18 +77,18 @@
 			@NotImplementedException!
 
 		this.download = () => {
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 
 		this.set-avatar = () => {
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 			@update-avatar this.I, null, this.file
 
 		this.set-banner = () => {
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 			@update-banner this.I, null, this.file
 
 		this.set-wallpaper = () => {
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 			@update-wallpaper this.I, null, this.file
 
 		this.add-app = () => {
diff --git a/src/web/app/desktop/tags/drive/file.tag b/src/web/app/desktop/tags/drive/file.tag
index 7016f7429..58c6b40a4 100644
--- a/src/web/app/desktop/tags/drive/file.tag
+++ b/src/web/app/desktop/tags/drive/file.tag
@@ -177,8 +177,8 @@
 
 			this.is-contextmenu-showing = true
 			this.update();
-			ctx = document.body.appendChild document.createElement 'mk-drive-browser-file-contextmenu' 
-			ctx = riot.mount ctx, do
+			ctx = document.body.appendChild(document.createElement('mk-drive-browser-file-contextmenu'));
+ 			ctx = riot.mount ctx, do
 				browser: this.browser
 				file: this.file
 			ctx = ctx.0
diff --git a/src/web/app/desktop/tags/drive/folder-contextmenu.tag b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
index 92fb5457c..833eff42e 100644
--- a/src/web/app/desktop/tags/drive/folder-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
@@ -21,11 +21,11 @@
 		this.mixin('api');
 		this.mixin('input-dialog');
 
-		this.browser = this.opts.browser
-		this.folder = this.opts.folder
+		this.browser = this.opts.browser;
+		this.folder = this.opts.folder;
 
-		this.open = (pos) => {
-			this.refs.ctx.open pos
+		this.open = pos => {
+			this.refs.ctx.open(pos);
 
 			this.refs.ctx.on('closed', () => {
 				this.trigger('closed');
@@ -33,29 +33,25 @@
 
 		this.move = () => {
 			this.browser.move this.folder.id
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 
-		this.new-window = () => {
-			this.browser.new-window this.folder.id
-			this.refs.ctx.close!
+		this.newWindow = () => {
+			this.browser.newWindow this.folder.id
+			this.refs.ctx.close();
 
-		this.create-folder = () => {
-			this.browser.create-folder!
-			this.refs.ctx.close!
-
-		this.upload = () => {
-			this.browser.select-lcoal-file!
-			this.refs.ctx.close!
+		this.createFolder = () => {
+			this.browser.createFolder();
+			this.refs.ctx.close();
 
 		this.rename = () => {
-			this.refs.ctx.close!
+			this.refs.ctx.close();
 
 			name <~ @input-dialog do
 				'フォルダ名の変更'
 				'新しいフォルダ名を入力してください'
 				this.folder.name
 
-			this.api 'drive/folders/update' do
+			this.api('drive/folders/update', {
 				folder_id: this.folder.id
 				name: name
 			.then =>
diff --git a/src/web/app/desktop/tags/drive/folder.tag b/src/web/app/desktop/tags/drive/folder.tag
index 02215dac3..fff3c13eb 100644
--- a/src/web/app/desktop/tags/drive/folder.tag
+++ b/src/web/app/desktop/tags/drive/folder.tag
@@ -115,7 +115,7 @@
 			if obj.type == 'file' 
 				file = obj.id
 				this.browser.remove-file file
-				this.api 'drive/files/update' do
+				this.api('drive/files/update', {
 					file_id: file
 					folder_id: this.folder.id
 				.then =>
@@ -130,7 +130,7 @@
 				if folder == this.folder.id
 					return false
 				this.browser.remove-folder folder
-				this.api 'drive/folders/update' do
+				this.api('drive/folders/update', {
 					folder_id: folder
 					parent_id: this.folder.id
 				.then =>
@@ -167,8 +167,8 @@
 
 			this.is-contextmenu-showing = true
 			this.update();
-			ctx = document.body.appendChild document.createElement 'mk-drive-browser-folder-contextmenu' 
-			ctx = riot.mount ctx, do
+			ctx = document.body.appendChild(document.createElement('mk-drive-browser-folder-contextmenu'));
+ 			ctx = riot.mount ctx, do
 				browser: this.browser
 				folder: this.folder
 			ctx = ctx.0
diff --git a/src/web/app/desktop/tags/drive/nav-folder.tag b/src/web/app/desktop/tags/drive/nav-folder.tag
index f0dab487e..3f57fc129 100644
--- a/src/web/app/desktop/tags/drive/nav-folder.tag
+++ b/src/web/app/desktop/tags/drive/nav-folder.tag
@@ -69,7 +69,7 @@
 			if obj.type == 'file' 
 				file = obj.id
 				this.browser.remove-file file
-				this.api 'drive/files/update' do
+				this.api('drive/files/update', {
 					file_id: file
 					folder_id: if this.folder? then this.folder.id else null
 				.then =>
@@ -84,7 +84,7 @@
 				if this.folder? and folder == this.folder.id
 					return false
 				this.browser.remove-folder folder
-				this.api 'drive/folders/update' do
+				this.api('drive/folders/update', {
 					folder_id: folder
 					parent_id: if this.folder? then this.folder.id else null
 				.then =>
diff --git a/src/web/app/desktop/tags/follow-button.tag b/src/web/app/desktop/tags/follow-button.tag
index 09ef98422..7b5ab7d0e 100644
--- a/src/web/app/desktop/tags/follow-button.tag
+++ b/src/web/app/desktop/tags/follow-button.tag
@@ -77,7 +77,7 @@
 		this.wait = false
 
 		this.on('mount', () => {
-			this.user-promise.then (user) =>
+			this.user-promise}).then((user) => {
 				this.user = user
 				this.init = false
 				this.update();
@@ -101,7 +101,7 @@
 		this.onclick = () => {
 			this.wait = true
 			if this.user.is_following
-				this.api 'following/delete' do
+				this.api('following/delete', {
 					user_id: this.user.id
 				.then =>
 					this.user.is_following = false
@@ -111,7 +111,7 @@
 					this.wait = false
 					this.update();
 			else
-				this.api 'following/create' do
+				this.api('following/create', {
 					user_id: this.user.id
 				.then =>
 					this.user.is_following = true
diff --git a/src/web/app/desktop/tags/following-setuper.tag b/src/web/app/desktop/tags/following-setuper.tag
index c4adfbd86..6381e4d8d 100644
--- a/src/web/app/desktop/tags/following-setuper.tag
+++ b/src/web/app/desktop/tags/following-setuper.tag
@@ -140,10 +140,10 @@
 			this.users = null
 			this.update();
 
-			this.api 'users/recommendation' do
+			this.api('users/recommendation', {
 				limit: @limit
 				offset: @limit * this.page
-			.then (users) =>
+			}).then((users) => {
 				this.loading = false
 				this.users = users
 				this.update();
diff --git a/src/web/app/desktop/tags/home-widgets/mentions.tag b/src/web/app/desktop/tags/home-widgets/mentions.tag
index d3f9eac3a..4ae17647f 100644
--- a/src/web/app/desktop/tags/home-widgets/mentions.tag
+++ b/src/web/app/desktop/tags/home-widgets/mentions.tag
@@ -72,9 +72,9 @@
 					this.refs.timeline.focus();
 
 		this.fetch = (cb) => {
-			this.api 'posts/mentions' do
+			this.api('posts/mentions', {
 				following: this.mode == 'following' 
-			.then (posts) =>
+			}).then((posts) => {
 				this.is-loading = false
 				this.is-empty = posts.length == 0
 				this.update();
@@ -89,10 +89,10 @@
 				return
 			this.more-loading = true
 			this.update();
-			this.api 'posts/mentions' do
+			this.api('posts/mentions', {
 				following: this.mode == 'following' 
 				max_id: this.refs.timeline.tail!.id
-			.then (posts) =>
+			}).then((posts) => {
 				this.more-loading = false
 				this.update();
 				this.refs.timeline.prepend-posts posts
diff --git a/src/web/app/desktop/tags/home-widgets/photo-stream.tag b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
index c606fac64..042e3ea20 100644
--- a/src/web/app/desktop/tags/home-widgets/photo-stream.tag
+++ b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
@@ -66,10 +66,10 @@
 		this.on('mount', () => {
 			this.stream.on 'drive_file_created' this.on-stream-drive-file-created
 
-			this.api 'drive/stream' do
+			this.api('drive/stream', {
 				type: 'image/*'
 				limit: 9images
-			.then (images) =>
+			}).then((images) => {
 				this.initializing = false
 				this.images = images
 				this.update();
diff --git a/src/web/app/desktop/tags/home-widgets/rss-reader.tag b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
index d44f76b16..98af55cb5 100644
--- a/src/web/app/desktop/tags/home-widgets/rss-reader.tag
+++ b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
@@ -81,7 +81,7 @@
 		this.fetch = () => {
 			this.api CONFIG.url + '/api:rss' do
 				url: @url
-			.then (feed) =>
+			}).then((feed) => {
 				this.items = feed.rss.channel.item
 				this.initializing = false
 				this.update();
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index 6e3e867e5..30acc75ac 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -68,7 +68,7 @@
 
 		this.load = (cb) => {
 			this.api 'posts/timeline' 
-			.then (posts) =>
+			}).then((posts) => {
 				this.is-loading = false
 				this.is-empty = posts.length == 0
 				this.update();
@@ -83,9 +83,9 @@
 				return
 			this.more-loading = true
 			this.update();
-			this.api 'posts/timeline' do
+			this.api('posts/timeline', {
 				max_id: this.refs.timeline.tail!.id
-			.then (posts) =>
+			}).then((posts) => {
 				this.more-loading = false
 				this.update();
 				this.refs.timeline.prepend-posts posts
diff --git a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
index 64c9c04e9..63a8d1571 100644
--- a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
+++ b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
@@ -132,10 +132,10 @@
 			this.loading = true
 			this.users = null
 			if not quiet then this.update();
-			this.api 'users/recommendation' do
+			this.api('users/recommendation', {
 				limit: @limit
 				offset: @limit * this.page
-			.then (users) =>
+			}).then((users) => {
 				this.loading = false
 				this.users = users
 				this.update();
diff --git a/src/web/app/desktop/tags/images-viewer.tag b/src/web/app/desktop/tags/images-viewer.tag
index 84190d34d..986debab4 100644
--- a/src/web/app/desktop/tags/images-viewer.tag
+++ b/src/web/app/desktop/tags/images-viewer.tag
@@ -38,8 +38,8 @@
 			this.refs.view.style.background-position = xp + '% ' + yp + '%'
 
 		this.click = () => {
-			dialog = document.body.appendChild document.createElement 'mk-image-dialog' 
-			riot.mount dialog, do
+			dialog = document.body.appendChild(document.createElement('mk-image-dialog'));
+ 			riot.mount dialog, do
 				image: @image
 	</script>
 </mk-images-viewer>
diff --git a/src/web/app/desktop/tags/input-dialog.tag b/src/web/app/desktop/tags/input-dialog.tag
index b5aefcd16..dbfd1cfc7 100644
--- a/src/web/app/desktop/tags/input-dialog.tag
+++ b/src/web/app/desktop/tags/input-dialog.tag
@@ -141,12 +141,12 @@
 
 		this.cancel = () => {
 			this.done = false
-			this.refs.window.close!
+			this.refs.window.close();
 
 		this.ok = () => {
 			if not @allow-empty and @text.value == '' then return
 			this.done = true
-			this.refs.window.close!
+			this.refs.window.close();
 
 		this.on-keydown = (e) => {
 			if e.which == 13 // Enter
diff --git a/src/web/app/desktop/tags/messaging/window.tag b/src/web/app/desktop/tags/messaging/window.tag
index 2d9a060d6..208404d15 100644
--- a/src/web/app/desktop/tags/messaging/window.tag
+++ b/src/web/app/desktop/tags/messaging/window.tag
@@ -24,8 +24,8 @@
 				this.unmount();
 
 			this.refs.window.refs.index.on('navigate-user', user => {
-				w = document.body.appendChild document.createElement 'mk-messaging-room-window' 
-				riot.mount w, do
+				w = document.body.appendChild(document.createElement('mk-messaging-room-window'));
+ 				riot.mount w, do
 					user: user
 	</script>
 </mk-messaging-window>
diff --git a/src/web/app/desktop/tags/notifications.tag b/src/web/app/desktop/tags/notifications.tag
index 39d86c5e2..2db27a4fc 100644
--- a/src/web/app/desktop/tags/notifications.tag
+++ b/src/web/app/desktop/tags/notifications.tag
@@ -187,7 +187,7 @@
 
 		this.on('mount', () => {
 			this.api 'i/notifications' 
-			.then (notifications) =>
+			}).then((notifications) => {
 				this.notifications = notifications
 				this.loading = false
 				this.update();
diff --git a/src/web/app/desktop/tags/post-detail-sub.tag b/src/web/app/desktop/tags/post-detail-sub.tag
index b61898f67..f5fec6f6a 100644
--- a/src/web/app/desktop/tags/post-detail-sub.tag
+++ b/src/web/app/desktop/tags/post-detail-sub.tag
@@ -125,13 +125,13 @@
 
 		this.like = () => {
 			if this.post.is_liked
-				this.api 'posts/likes/delete' do
+				this.api('posts/likes/delete', {
 					post_id: this.post.id
 				.then =>
 					this.post.is_liked = false
 					this.update();
 			else
-				this.api 'posts/likes/create' do
+				this.api('posts/likes/create', {
 					post_id: this.post.id
 				.then =>
 					this.post.is_liked = true
diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag
index 958b0c681..3b5671452 100644
--- a/src/web/app/desktop/tags/post-detail.tag
+++ b/src/web/app/desktop/tags/post-detail.tag
@@ -342,9 +342,9 @@
 
 		this.on('mount', () => {
 
-			this.api 'posts/show' do
+			this.api('posts/show', {
 				post_id: this.opts.post
-			.then (post) =>
+			}).then((post) => {
 				this.fetching = false
 				this.post = post
 				this.trigger('loaded');
@@ -368,55 +368,55 @@
 					tokens
 						.filter (t) -> t.type == 'link' 
 						.map (t) =>
-							this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-							riot.mount this.preview, do
+							this.preview = this.refs.text.appendChild(document.createElement('mk-url-preview'));
+ 							riot.mount this.preview, do
 								url: t.content
 
 				// Get likes
-				this.api 'posts/likes' do
+				this.api('posts/likes', {
 					post_id: this.p.id
 					limit: 8
-				.then (likes) =>
+				}).then((likes) => {
 					this.likes = likes
 					this.update();
 
 				// Get reposts
-				this.api 'posts/reposts' do
+				this.api('posts/reposts', {
 					post_id: this.p.id
 					limit: 8
-				.then (reposts) =>
+				}).then((reposts) => {
 					this.reposts = reposts
 					this.update();
 
 				// Get replies
-				this.api 'posts/replies' do
+				this.api('posts/replies', {
 					post_id: this.p.id
 					limit: 8
-				.then (replies) =>
+				}).then((replies) => {
 					this.replies = replies
 					this.update();
 
 				this.update();
 
 		this.reply = () => {
-			form = document.body.appendChild document.createElement 'mk-post-form-window' 
-			riot.mount form, do
+			form = document.body.appendChild(document.createElement('mk-post-form-window'));
+ 			riot.mount form, do
 				reply: this.p
 
 		this.repost = () => {
-			form = document.body.appendChild document.createElement 'mk-repost-form-window' 
-			riot.mount form, do
+			form = document.body.appendChild(document.createElement('mk-repost-form-window'));
+ 			riot.mount form, do
 				post: this.p
 
 		this.like = () => {
 			if this.p.is_liked
-				this.api 'posts/likes/delete' do
+				this.api('posts/likes/delete', {
 					post_id: this.p.id
 				.then =>
 					this.p.is_liked = false
 					this.update();
 			else
-				this.api 'posts/likes/create' do
+				this.api('posts/likes/create', {
 					post_id: this.p.id
 				.then =>
 					this.p.is_liked = true
@@ -426,9 +426,9 @@
 			this.loading-context = true
 
 			// Get context
-			this.api 'posts/context' do
+			this.api('posts/context', {
 				post_id: this.p.reply_to_id
-			.then (context) =>
+			}).then((context) => {
 				this.context = context.reverse!
 				this.loading-context = false
 				this.update();
diff --git a/src/web/app/desktop/tags/post-form-window.tag b/src/web/app/desktop/tags/post-form-window.tag
index bb68de5f0..8f5bf1a51 100644
--- a/src/web/app/desktop/tags/post-form-window.tag
+++ b/src/web/app/desktop/tags/post-form-window.tag
@@ -42,7 +42,7 @@
 				this.unmount();
 
 			this.refs.window.refs.form.on('post', () => {
-				this.refs.window.close!
+				this.refs.window.close();
 
 			this.refs.window.refs.form.on('change-uploading-files', (files) => {
 				this.uploading-files = files
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index ed56e2a11..fe435c4e4 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -405,8 +405,8 @@
 			this.refs.file.click();
 
 		this.select-file-from-drive = () => {
-			browser = document.body.appendChild document.createElement 'mk-select-file-from-drive-window' 
-			i = riot.mount browser, do
+			browser = document.body.appendChild(document.createElement('mk-select-file-from-drive-window'));
+ 			i = riot.mount browser, do
 				multiple: true
 			i[0].one 'selected' (files) =>
 				files.forEach @add-file
@@ -444,12 +444,12 @@
 				then this.files.map (f) -> f.id
 				else undefined
 
-			this.api 'posts/create' do
+			this.api('posts/create', {
 				text: this.refs.text.value
 				media_ids: files
 				reply_to_id: if @in-reply-to-post? then @in-reply-to-post.id else undefined
 				poll: if this.poll then this.refs.poll.get! else undefined
-			.then (data) =>
+			}).then((data) => {
 				this.trigger('post');
 				@notify if @in-reply-to-post? then '返信しました!' else '投稿しました!'
 			.catch (err) =>
diff --git a/src/web/app/desktop/tags/post-status-graph.tag b/src/web/app/desktop/tags/post-status-graph.tag
index f4a890a0c..5f6a667eb 100644
--- a/src/web/app/desktop/tags/post-status-graph.tag
+++ b/src/web/app/desktop/tags/post-status-graph.tag
@@ -20,22 +20,22 @@
 			this.post = post
 			this.update();
 
-			this.api 'aggregation/posts/like' do
+			this.api('aggregation/posts/like', {
 				post_id: this.post.id
 				limit: 30days
-			.then (likes) =>
+			}).then((likes) => {
 				likes = likes.reverse!
 
-				this.api 'aggregation/posts/repost' do
+				this.api('aggregation/posts/repost', {
 					post_id: this.post.id
 					limit: 30days
-				.then (repost) =>
+				}).then((repost) => {
 					repost = repost.reverse!
 
-					this.api 'aggregation/posts/reply' do
+					this.api('aggregation/posts/reply', {
 						post_id: this.post.id
 						limit: 30days
-					.then (replies) =>
+					}).then((replies) => {
 						replies = replies.reverse!
 
 						new Chart this.refs.canv, do
diff --git a/src/web/app/desktop/tags/progress-dialog.tag b/src/web/app/desktop/tags/progress-dialog.tag
index da0ed16d7..cba4e3404 100644
--- a/src/web/app/desktop/tags/progress-dialog.tag
+++ b/src/web/app/desktop/tags/progress-dialog.tag
@@ -89,6 +89,6 @@
 			this.update();
 
 		this.close = () => {
-			this.refs.window.close!
+			this.refs.window.close();
 	</script>
 </mk-progress-dialog>
diff --git a/src/web/app/desktop/tags/repost-form-window.tag b/src/web/app/desktop/tags/repost-form-window.tag
index 7af67094b..d7521caab 100644
--- a/src/web/app/desktop/tags/repost-form-window.tag
+++ b/src/web/app/desktop/tags/repost-form-window.tag
@@ -16,14 +16,14 @@
 			tag = e.target.tag-name.to-lower-case!
 			if tag != 'input' and tag != 'textarea' 
 				if e.which == 27 // Esc
-					this.refs.window.close!
+					this.refs.window.close();
 
 		this.on('mount', () => {
 			this.refs.window.refs.form.on('cancel', () => {
-				this.refs.window.close!
+				this.refs.window.close();
 
 			this.refs.window.refs.form.on('posted', () => {
-				this.refs.window.close!
+				this.refs.window.close();
 
 			document.addEventListener 'keydown' this.on-document-keydown
 
diff --git a/src/web/app/desktop/tags/repost-form.tag b/src/web/app/desktop/tags/repost-form.tag
index 319b42dd0..c3e3e02df 100644
--- a/src/web/app/desktop/tags/repost-form.tag
+++ b/src/web/app/desktop/tags/repost-form.tag
@@ -125,10 +125,10 @@
 
 		this.ok = () => {
 			this.wait = true
-			this.api 'posts/create' do
+			this.api('posts/create', {
 				repost_id: this.opts.post.id
 				text: if @quote then this.refs.text.value else undefined
-			.then (data) =>
+			}).then((data) => {
 				this.trigger('posted');
 				@notify 'Repostしました!'
 			.catch (err) =>
diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag
index dd3b8e66e..bad055eb0 100644
--- a/src/web/app/desktop/tags/search-posts.tag
+++ b/src/web/app/desktop/tags/search-posts.tag
@@ -41,9 +41,9 @@
 			document.addEventListener 'keydown' this.on-document-keydown
 			window.addEventListener 'scroll' this.on-scroll
 
-			this.api 'posts/search' do
+			this.api('posts/search', {
 				query: @query
-			.then (posts) =>
+			}).then((posts) => {
 				this.is-loading = false
 				this.is-empty = posts.length == 0
 				this.update();
@@ -67,10 +67,10 @@
 				return
 			this.more-loading = true
 			this.update();
-			this.api 'posts/search' do
+			this.api('posts/search', {
 				query: @query
 				page: this.page + 1
-			.then (posts) =>
+			}).then((posts) => {
 				this.more-loading = false
 				this.page++
 				this.update();
diff --git a/src/web/app/desktop/tags/select-file-from-drive-window.tag b/src/web/app/desktop/tags/select-file-from-drive-window.tag
index 6979a5521..45ece233f 100644
--- a/src/web/app/desktop/tags/select-file-from-drive-window.tag
+++ b/src/web/app/desktop/tags/select-file-from-drive-window.tag
@@ -149,13 +149,13 @@
 				this.unmount();
 
 		this.close = () => {
-			this.refs.window.close!
+			this.refs.window.close();
 
 		this.upload = () => {
 			this.refs.window.refs.browser.select-local-file!
 
 		this.ok = () => {
 			this.trigger 'selected' this.file
-			this.refs.window.close!
+			this.refs.window.close();
 	</script>
 </mk-select-file-from-drive-window>
diff --git a/src/web/app/desktop/tags/settings-window.tag b/src/web/app/desktop/tags/settings-window.tag
index 89219fccf..b3f0bb457 100644
--- a/src/web/app/desktop/tags/settings-window.tag
+++ b/src/web/app/desktop/tags/settings-window.tag
@@ -20,6 +20,6 @@
 				this.unmount();
 
 		this.close = () => {
-			this.refs.window.close!
+			this.refs.window.close();
 	</script>
 </mk-settings-window>
diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag
index e4a83738e..e43a512af 100644
--- a/src/web/app/desktop/tags/settings.tag
+++ b/src/web/app/desktop/tags/settings.tag
@@ -212,31 +212,31 @@
 			@update-avatar this.I
 
 		this.update-account = () => {
-			this.api 'i/update' do
+			this.api('i/update', {
 				name: this.refs.account-name.value
 				location: this.refs.account-location.value
 				bio: this.refs.account-bio.value
 				birthday: this.refs.account-birthday.value
-			.then (i) =>
+			}).then((i) => {
 				alert 'ok' 
 			.catch (err) =>
 				console.error err
 
 		this.update-cache = () => {
 			this.I.data.cache = !this.I.data.cache
-			this.api 'i/appdata/set' do
+			this.api('i/appdata/set', {
 				data: JSON.stringify do
 					cache: this.I.data.cache
 
 		this.update-debug = () => {
 			this.I.data.debug = !this.I.data.debug
-			this.api 'i/appdata/set' do
+			this.api('i/appdata/set', {
 				data: JSON.stringify do
 					debug: this.I.data.debug
 
 		this.update-nya = () => {
 			this.I.data.nya = !this.I.data.nya
-			this.api 'i/appdata/set' do
+			this.api('i/appdata/set', {
 				data: JSON.stringify do
 					nya: this.I.data.nya
 	</script>
diff --git a/src/web/app/desktop/tags/timeline-post.tag b/src/web/app/desktop/tags/timeline-post.tag
index 0d572981c..5b656f812 100644
--- a/src/web/app/desktop/tags/timeline-post.tag
+++ b/src/web/app/desktop/tags/timeline-post.tag
@@ -55,8 +55,13 @@
 				<button class={ liked: p.is_liked } onclick={ like } title="善哉"><i class="fa fa-thumbs-o-up"></i>
 					<p class="count" if={ p.likes_count > 0 }>{ p.likes_count }</p>
 				</button>
-				<button onclick={ NotImplementedException }><i class="fa fa-ellipsis-h"></i></button>
-				<button onclick={ toggleDetail } title="詳細"><i class="fa fa-caret-down" if={ !isDetailOpened }></i><i class="fa fa-caret-up" if={ isDetailOpened }></i></button>
+				<button onclick={ NotImplementedException }>
+					<i class="fa fa-ellipsis-h"></i>
+				</button>
+				<button onclick={ toggleDetail } title="詳細">
+					<i class="fa fa-caret-down" if={ !isDetailOpened }></i>
+					<i class="fa fa-caret-up" if={ isDetailOpened }></i>
+				</button>
 			</footer>
 		</div>
 	</article>
@@ -328,46 +333,45 @@
 		this.isDetailOpened = false;
 
 		this.on('mount', () => {
-			if this.p.text?
-				tokens = if this.p._highlight?
-					then @analyze this.p._highlight
-					else @analyze this.p.text
+			if (this.p.text) {
+				const tokens = this.analyze(this.p.text);
 
-				this.refs.text.innerHTML = this.refs.text.innerHTML.replace '<p class="dummy"></p>' if this.p._highlight?
-					then @compile tokens, true, false
-					else @compile tokens
+				this.refs.text.innerHTML = this.refs.text.innerHTML.replace('<p class="dummy"></p>', this.compile(tokens));
 
-				this.refs.text.children.forEach (e) =>
-					if e.tag-name == 'MK-URL' 
-						riot.mount e
+				this.refs.text.children.forEach(e => {
+					if (e.tagName == 'MK-URL') riot.mount(e);
+				});
 
 				// URLをプレビュー
 				tokens
-					.filter (t) -> t.type == 'link' 
-					.map (t) =>
-						this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-						riot.mount this.preview, do
-							url: t.content
+				.filter(t => t.type == 'link')
+				.map(t => {
+					riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
+						url: t.content
+					});
+				});
+			}
+		});
 
 		this.reply = () => {
-			form = document.body.appendChild document.createElement 'mk-post-form-window' 
-			riot.mount form, do
+			form = document.body.appendChild(document.createElement('mk-post-form-window'));
+ 			riot.mount form, do
 				reply: this.p
 
 		this.repost = () => {
-			form = document.body.appendChild document.createElement 'mk-repost-form-window' 
-			riot.mount form, do
+			form = document.body.appendChild(document.createElement('mk-repost-form-window'));
+ 			riot.mount form, do
 				post: this.p
 
 		this.like = () => {
 			if this.p.is_liked
-				this.api 'posts/likes/delete' do
+				this.api('posts/likes/delete', {
 					post_id: this.p.id
 				.then =>
 					this.p.is_liked = false
 					this.update();
 			else
-				this.api 'posts/likes/create' do
+				this.api('posts/likes/create', {
 					post_id: this.p.id
 				.then =>
 					this.p.is_liked = true
diff --git a/src/web/app/desktop/tags/ui-header-account.tag b/src/web/app/desktop/tags/ui-header-account.tag
index 21382bc53..334b69e21 100644
--- a/src/web/app/desktop/tags/ui-header-account.tag
+++ b/src/web/app/desktop/tags/ui-header-account.tag
@@ -165,11 +165,11 @@
 		this.is-open = false
 
 		this.on('before-unmount', () => {
-			@close!
+			@close();
 
 		this.toggle = () => {
 			if @is-open
-				@close!
+				@close();
 			else
 				@open!
 
@@ -190,17 +190,17 @@
 		this.mousedown = (e) => {
 			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
-				@close!
+				@close();
 			return false
 
 		this.drive = () => {
-			@close!
-			riot.mount document.body.appendChild document.createElement 'mk-drive-browser-window' 
-
+			@close();
+			riot.mount document.body.appendChild(document.createElement('mk-drive-browser-window'));
+ 
 		this.settings = () => {
-			@close!
-			riot.mount document.body.appendChild document.createElement 'mk-settings-window' 
-
+			@close();
+			riot.mount document.body.appendChild(document.createElement('mk-settings-window'));
+ 
 		function contains(parent, child)
 			node = child.parentNode
 			while node?
diff --git a/src/web/app/desktop/tags/ui-header-nav.tag b/src/web/app/desktop/tags/ui-header-nav.tag
index a884aa0b2..93819963e 100644
--- a/src/web/app/desktop/tags/ui-header-nav.tag
+++ b/src/web/app/desktop/tags/ui-header-nav.tag
@@ -89,7 +89,7 @@
 
 				// Fetch count of unread messaging messages
 				this.api 'messaging/unread' 
-				.then (count) =>
+				}).then((count) => {
 					if count.count > 0
 						this.has-unread-messaging-messages = true
 						this.update();
@@ -107,7 +107,7 @@
 				this.update();
 
 			this.messaging = () => {
-				riot.mount document.body.appendChild document.createElement 'mk-messaging-window' 
-		</script>
+				riot.mount document.body.appendChild(document.createElement('mk-messaging-window'));
+ 		</script>
 	</ul>
 </mk-ui-header-nav>
diff --git a/src/web/app/desktop/tags/ui-header-notifications.tag b/src/web/app/desktop/tags/ui-header-notifications.tag
index fac90bb83..31dc45d0d 100644
--- a/src/web/app/desktop/tags/ui-header-notifications.tag
+++ b/src/web/app/desktop/tags/ui-header-notifications.tag
@@ -79,7 +79,7 @@
 
 		this.toggle = () => {
 			if @is-open
-				@close!
+				@close();
 			else
 				@open!
 
@@ -100,7 +100,7 @@
 		this.mousedown = (e) => {
 			e.preventDefault();
 			if (!contains this.root, e.target) and (this.root != e.target)
-				@close!
+				@close();
 			return false
 
 		function contains(parent, child)
diff --git a/src/web/app/desktop/tags/ui-header-post-button.tag b/src/web/app/desktop/tags/ui-header-post-button.tag
index 3f339beb6..ca380b06e 100644
--- a/src/web/app/desktop/tags/ui-header-post-button.tag
+++ b/src/web/app/desktop/tags/ui-header-post-button.tag
@@ -35,7 +35,8 @@
 
 	</style>
 	<script>
-		this.post = (e) => {
-			this.parent.parent.open-post-form!
+		this.post = e => {
+			this.parent.parent.openPostForm();
+		};
 	</script>
 </mk-ui-header-post-button>
diff --git a/src/web/app/desktop/tags/ui-header.tag b/src/web/app/desktop/tags/ui-header.tag
index 9dd1ace6b..4ab178930 100644
--- a/src/web/app/desktop/tags/ui-header.tag
+++ b/src/web/app/desktop/tags/ui-header.tag
@@ -80,6 +80,5 @@
 									display none
 
 	</style>
-
 	<script>this.mixin('i');</script>
 </mk-ui-header>
diff --git a/src/web/app/desktop/tags/user-friends-graph.tag b/src/web/app/desktop/tags/user-friends-graph.tag
index 76827fbda..8932d596f 100644
--- a/src/web/app/desktop/tags/user-friends-graph.tag
+++ b/src/web/app/desktop/tags/user-friends-graph.tag
@@ -19,16 +19,16 @@
 			this.user = user
 			this.update();
 
-			this.api 'aggregation/users/followers' do
+			this.api('aggregation/users/followers', {
 				user_id: this.user.id
 				limit: 30days
-			.then (followers) =>
+			}).then((followers) => {
 				followers = followers.reverse!
 
-				this.api 'aggregation/users/following' do
+				this.api('aggregation/users/following', {
 					user_id: this.user.id
 					limit: 30days
-				.then (following) =>
+				}).then((following) => {
 					following = following.reverse!
 
 					new Chart this.refs.canv, do
diff --git a/src/web/app/desktop/tags/user-likes-graph.tag b/src/web/app/desktop/tags/user-likes-graph.tag
index 6030efdaf..5639ee36e 100644
--- a/src/web/app/desktop/tags/user-likes-graph.tag
+++ b/src/web/app/desktop/tags/user-likes-graph.tag
@@ -19,10 +19,10 @@
 			this.user = user
 			this.update();
 
-			this.api 'aggregation/users/like' do
+			this.api('aggregation/users/like', {
 				user_id: this.user.id
 				limit: 30days
-			.then (likes) =>
+			}).then((likes) => {
 				likes = likes.reverse!
 
 				new Chart this.refs.canv, do
diff --git a/src/web/app/desktop/tags/user-photos.tag b/src/web/app/desktop/tags/user-photos.tag
index 58ba1b73d..9cde9b8c4 100644
--- a/src/web/app/desktop/tags/user-photos.tag
+++ b/src/web/app/desktop/tags/user-photos.tag
@@ -67,15 +67,15 @@
 		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
 
 		this.on('mount', () => {
-			this.user-promise.then (user) =>
+			this.user-promise}).then((user) => {
 				this.user = user
 				this.update();
 
-				this.api 'users/posts' do
+				this.api('users/posts', {
 					user_id: this.user.id
 					with_media: true
 					limit: 9posts
-				.then (posts) =>
+				}).then((posts) => {
 					this.initializing = false
 					posts.forEach (post) =>
 						post.media.forEach (image) =>
diff --git a/src/web/app/desktop/tags/user-posts-graph.tag b/src/web/app/desktop/tags/user-posts-graph.tag
index 0be3abb4e..d1760c6b3 100644
--- a/src/web/app/desktop/tags/user-posts-graph.tag
+++ b/src/web/app/desktop/tags/user-posts-graph.tag
@@ -19,10 +19,10 @@
 			this.user = user
 			this.update();
 
-			this.api 'aggregation/users/post' do
+			this.api('aggregation/users/post', {
 				user_id: this.user.id
 				limit: 30days
-			.then (data) =>
+			}).then((data) => {
 				data = data.reverse!
 				new Chart this.refs.canv, do
 					type: 'line' 
diff --git a/src/web/app/desktop/tags/user-preview.tag b/src/web/app/desktop/tags/user-preview.tag
index 6d4f0b2b0..8dd6551c4 100644
--- a/src/web/app/desktop/tags/user-preview.tag
+++ b/src/web/app/desktop/tags/user-preview.tag
@@ -105,16 +105,16 @@
 		this.user-promise = 
 			if typeof @u == 'string' 
 				new Promise (resolve, reject) =>
-					this.api 'users/show' do
+					this.api('users/show', {
 						user_id: if @u.0 == '@' then undefined else @u
 						username: if @u.0 == '@' then @u.substr 1 else undefined
-					.then (user) =>
+					}).then((user) => {
 						resolve user
 			else
 				Promise.resolve @u
 
 		this.on('mount', () => {
-			this.user-promise.then (user) =>
+			this.user-promise}).then((user) => {
 				this.user = user
 				this.update();
 
diff --git a/src/web/app/desktop/tags/user-profile.tag b/src/web/app/desktop/tags/user-profile.tag
index 8df631ade..36c9f7f95 100644
--- a/src/web/app/desktop/tags/user-profile.tag
+++ b/src/web/app/desktop/tags/user-profile.tag
@@ -87,13 +87,13 @@
 		this.user = this.opts.user
 
 		this.show-following = () => {
-			window = document.body.appendChild document.createElement 'mk-user-following-window' 
-			riot.mount window, do
+			window = document.body.appendChild(document.createElement('mk-user-following-window'));
+ 			riot.mount window, do
 				user: this.user
 
 		this.show-followers = () => {
-			window = document.body.appendChild document.createElement 'mk-user-followers-window' 
-			riot.mount window, do
+			window = document.body.appendChild(document.createElement('mk-user-followers-window'));
+ 			riot.mount window, do
 				user: this.user
 	</script>
 </mk-user-profile>
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index 405097e06..acced7fc3 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -63,7 +63,7 @@
 			document.addEventListener 'keydown' this.on-document-keydown
 			window.addEventListener 'scroll' this.on-scroll
 
-			this.user-promise.then (user) =>
+			this.user-promise}).then((user) => {
 				this.user = user
 				this.update();
 
@@ -82,10 +82,10 @@
 					this.refs.timeline.focus();
 
 		this.fetch = (cb) => {
-			this.api 'users/posts' do
+			this.api('users/posts', {
 				user_id: this.user.id
 				with_replies: this.mode == 'with-replies' 
-			.then (posts) =>
+			}).then((posts) => {
 				this.is-loading = false
 				this.is-empty = posts.length == 0
 				this.update();
@@ -100,11 +100,11 @@
 				return
 			this.more-loading = true
 			this.update();
-			this.api 'users/posts' do
+			this.api('users/posts', {
 				user_id: this.user.id
 				with_replies: this.mode == 'with-replies' 
 				max_id: this.refs.timeline.tail!.id
-			.then (posts) =>
+			}).then((posts) => {
 				this.more-loading = false
 				this.update();
 				this.refs.timeline.prepend-posts posts
diff --git a/src/web/app/desktop/tags/user.tag b/src/web/app/desktop/tags/user.tag
index a088d97db..9b64cf08e 100644
--- a/src/web/app/desktop/tags/user.tag
+++ b/src/web/app/desktop/tags/user.tag
@@ -40,9 +40,9 @@
 		this.user = null
 
 		this.on('mount', () => {
-			this.api 'users/show' do
+			this.api('users/show', {
 				username: this.username
-			.then (user) =>
+			}).then((user) => {
 				this.fetching = false
 				this.user = user
 				this.update();
diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index f83ccf3f8..33bb244fa 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -320,7 +320,7 @@
 
 		this.bg-click = () => {
 			if @can-close
-				@close!
+				@close();
 
 		this.on-body-mousedown = (e) => {
 			@top!
@@ -506,7 +506,7 @@
 				if @can-close
 					e.preventDefault();
 					e.stopPropagation();
-					@close!
+					@close();
 
 		function contains(parent, child)
 			node = child.parentNode
diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag
index d0906d638..6be1c5448 100644
--- a/src/web/app/dev/tags/new-app-form.tag
+++ b/src/web/app/dev/tags/new-app-form.tag
@@ -203,9 +203,9 @@
 				this.nid-state = 'wait' 
 				this.update();
 
-				this.api 'app/name_id/available' do
+				this.api('app/name_id/available', {
 					name_id: nid
-				.then (result) =>
+				}).then((result) => {
 					if result.available
 						this.nid-state = 'ok' 
 					else
@@ -225,9 +225,9 @@
 			this.refs.permission.query-selector-all 'input' .forEach (el) =>
 				if el.checked then permission.push el.value
 
-			locker = document.body.appendChild document.createElement 'mk-locker' 
-
-			this.api 'app/create' do
+			locker = document.body.appendChild(document.createElement('mk-locker'));
+ 
+			this.api('app/create', {
 				name: name
 				name_id: nid
 				description: description
diff --git a/src/web/app/dev/tags/pages/app.tag b/src/web/app/dev/tags/pages/app.tag
index 3512dd747..e6cadab1b 100644
--- a/src/web/app/dev/tags/pages/app.tag
+++ b/src/web/app/dev/tags/pages/app.tag
@@ -20,9 +20,9 @@
 		this.fetching = true
 
 		this.on('mount', () => {
-			this.api 'app/show' do
+			this.api('app/show', {
 				app_id: this.opts.app
-			.then (app) =>
+			}).then((app) => {
 				this.app = app
 				this.fetching = false
 				this.update();
diff --git a/src/web/app/dev/tags/pages/apps.tag b/src/web/app/dev/tags/pages/apps.tag
index 58e09e24e..c87141711 100644
--- a/src/web/app/dev/tags/pages/apps.tag
+++ b/src/web/app/dev/tags/pages/apps.tag
@@ -22,7 +22,7 @@
 
 		this.on('mount', () => {
 			this.api 'my/apps' 
-			.then (apps) =>
+			}).then((apps) => {
 				this.fetching = false
 				this.apps = apps
 				this.update();
diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag
index d0c9b87b9..8d4383f6e 100644
--- a/src/web/app/mobile/tags/drive.tag
+++ b/src/web/app/mobile/tags/drive.tag
@@ -206,9 +206,9 @@
 			this.loading = true
 			this.update();
 
-			this.api 'drive/folders/show' do
+			this.api('drive/folders/show', {
 				folder_id: target-folder
-			.then (folder) =>
+			}).then((folder) => {
 				this.folder = folder
 				this.hierarchyFolders = []
 
@@ -297,10 +297,10 @@
 			files-max = 20
 
 			// フォルダ一覧取得
-			this.api 'drive/folders' do
+			this.api('drive/folders', {
 				folder_id: if this.folder? then this.folder.id else null
 				limit: folders-max + 1
-			.then (folders) =>
+			}).then((folders) => {
 				if folders.length == folders-max + 1
 					this.more-folders = true
 					folders.pop!
@@ -310,10 +310,10 @@
 				console.error err
 
 			// ファイル一覧取得
-			this.api 'drive/files' do
+			this.api('drive/files', {
 				folder_id: if this.folder? then this.folder.id else null
 				limit: files-max + 1
-			.then (files) =>
+			}).then((files) => {
 				if files.length == files-max + 1
 					this.more-files = true
 					files.pop!
@@ -356,9 +356,9 @@
 			this.loading = true
 			this.update();
 
-			this.api 'drive/files/show' do
+			this.api('drive/files/show', {
 				file_id: file
-			.then (file) =>
+			}).then((file) => {
 				this.file = file
 				this.folder = null
 				this.hierarchyFolders = []
diff --git a/src/web/app/mobile/tags/drive/file-viewer.tag b/src/web/app/mobile/tags/drive/file-viewer.tag
index 5f1380ae8..5f2c5f61f 100644
--- a/src/web/app/mobile/tags/drive/file-viewer.tag
+++ b/src/web/app/mobile/tags/drive/file-viewer.tag
@@ -191,7 +191,7 @@
 		this.rename = () => {
 			name = window.prompt '名前を変更' this.file.name
 			if name? and name != '' and name != this.file.name
-				this.api 'drive/files/update' do
+				this.api('drive/files/update', {
 					file_id: this.file.id
 					name: name
 				.then =>
diff --git a/src/web/app/mobile/tags/follow-button.tag b/src/web/app/mobile/tags/follow-button.tag
index ff4c6586d..ecd0dc594 100644
--- a/src/web/app/mobile/tags/follow-button.tag
+++ b/src/web/app/mobile/tags/follow-button.tag
@@ -58,7 +58,7 @@
 		this.wait = false
 
 		this.on('mount', () => {
-			this.user-promise.then (user) =>
+			this.user-promise}).then((user) => {
 				this.user = user
 				this.init = false
 				this.update();
@@ -82,7 +82,7 @@
 		this.onclick = () => {
 			this.wait = true
 			if this.user.is_following
-				this.api 'following/delete' do
+				this.api('following/delete', {
 					user_id: this.user.id
 				.then =>
 					this.user.is_following = false
@@ -92,7 +92,7 @@
 					this.wait = false
 					this.update();
 			else
-				this.api 'following/create' do
+				this.api('following/create', {
 					user_id: this.user.id
 				.then =>
 					this.user.is_following = true
diff --git a/src/web/app/mobile/tags/home-timeline.tag b/src/web/app/mobile/tags/home-timeline.tag
index b308c4168..0d617c841 100644
--- a/src/web/app/mobile/tags/home-timeline.tag
+++ b/src/web/app/mobile/tags/home-timeline.tag
@@ -11,7 +11,7 @@
 
 		this.init = new Promise (res, rej) =>
 			this.api 'posts/timeline' 
-			.then (posts) =>
+			}).then((posts) => {
 				res posts
 				this.trigger('loaded');
 
@@ -26,7 +26,7 @@
 			this.stream.off 'unfollow' this.on-stream-unfollow
 
 		this.more = () => {
-			this.api 'posts/timeline' do
+			this.api('posts/timeline', {
 				max_id: this.refs.timeline.tail!.id
 
 		this.on-stream-post = (post) => {
diff --git a/src/web/app/mobile/tags/notifications.tag b/src/web/app/mobile/tags/notifications.tag
index ef53c025e..9fb695a43 100644
--- a/src/web/app/mobile/tags/notifications.tag
+++ b/src/web/app/mobile/tags/notifications.tag
@@ -66,7 +66,7 @@
 
 		this.on('mount', () => {
 			this.api 'i/notifications' 
-			.then (notifications) =>
+			}).then((notifications) => {
 				this.notifications = notifications
 				this.loading = false
 				this.update();
diff --git a/src/web/app/mobile/tags/page/messaging-room.tag b/src/web/app/mobile/tags/page/messaging-room.tag
index 6b699143c..934a7f877 100644
--- a/src/web/app/mobile/tags/page/messaging-room.tag
+++ b/src/web/app/mobile/tags/page/messaging-room.tag
@@ -13,9 +13,9 @@
 		this.fetching = true
 
 		this.on('mount', () => {
-			this.api 'users/show' do
+			this.api('users/show', {
 				username: this.opts.username
-			.then (user) =>
+			}).then(user => {
 				this.fetching = false
 				this.user = user
 				this.update();
diff --git a/src/web/app/mobile/tags/page/user-followers.tag b/src/web/app/mobile/tags/page/user-followers.tag
index 12338e796..75a2c5d27 100644
--- a/src/web/app/mobile/tags/page/user-followers.tag
+++ b/src/web/app/mobile/tags/page/user-followers.tag
@@ -18,9 +18,9 @@
 		this.on('mount', () => {
 			this.Progress.start();
 
-			this.api 'users/show' do
+			this.api('users/show', {
 				username: this.opts.user
-			.then (user) =>
+			}).then(user => {
 				this.user = user
 				this.fetching = false
 
diff --git a/src/web/app/mobile/tags/page/user-following.tag b/src/web/app/mobile/tags/page/user-following.tag
index 088c45832..44a054e82 100644
--- a/src/web/app/mobile/tags/page/user-following.tag
+++ b/src/web/app/mobile/tags/page/user-following.tag
@@ -18,9 +18,9 @@
 		this.on('mount', () => {
 			this.Progress.start();
 
-			this.api 'users/show' do
+			this.api('users/show', {
 				username: this.opts.user
-			.then (user) =>
+			}).then(user => {
 				this.user = user
 				this.fetching = false
 
diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag
index fee132d7d..61983a159 100644
--- a/src/web/app/mobile/tags/post-detail.tag
+++ b/src/web/app/mobile/tags/post-detail.tag
@@ -334,15 +334,15 @@
 		this.mixin('get-post-summary');
 		this.mixin('open-post-form');
 
-		this.fetching = true
-		this.loading-context = false
-		this.content = null
-		this.post = null
+		this.fetching = true;
+		this.loadingContext = false;
+		this.content = null;
+		this.post = null;
 
 		this.on('mount', () => {
-			this.api 'posts/show' do
+			this.api('posts/show', {
 				post_id: this.opts.post
-			.then (post) =>
+			}).then((post) => {
 				this.post = post
 				this.is-repost = this.post.repost?
 				this.p = if @is-repost then this.post.repost else this.post
@@ -363,54 +363,54 @@
 					tokens
 						.filter (t) -> t.type == 'link' 
 						.map (t) =>
-							this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-							riot.mount this.preview, do
+							this.preview = this.refs.text.appendChild(document.createElement('mk-url-preview'));
+ 							riot.mount this.preview, do
 								url: t.content
 
 				// Get likes
-				this.api 'posts/likes' do
+				this.api('posts/likes', {
 					post_id: this.p.id
 					limit: 8
-				.then (likes) =>
+				}).then((likes) => {
 					this.likes = likes
 					this.update();
 
 				// Get reposts
-				this.api 'posts/reposts' do
+				this.api('posts/reposts', {
 					post_id: this.p.id
 					limit: 8
-				.then (reposts) =>
+				}).then((reposts) => {
 					this.reposts = reposts
 					this.update();
 
 				// Get replies
-				this.api 'posts/replies' do
+				this.api('posts/replies', {
 					post_id: this.p.id
 					limit: 8
-				.then (replies) =>
+				}).then((replies) => {
 					this.replies = replies
 					this.update();
 
 		this.reply = () => {
-			@open-post-form do
+			this.openPostForm do
 				reply: this.p
 
 		this.repost = () => {
 			text = window.prompt '「' + @summary + '」をRepost'
 			if text?
-				this.api 'posts/create' do
+				this.api('posts/create', {
 					repost_id: this.p.id
 					text: if text == '' then undefined else text
 
 		this.like = () => {
 			if this.p.is_liked
-				this.api 'posts/likes/delete' do
+				this.api('posts/likes/delete', {
 					post_id: this.p.id
 				.then =>
 					this.p.is_liked = false
 					this.update();
 			else
-				this.api 'posts/likes/create' do
+				this.api('posts/likes/create', {
 					post_id: this.p.id
 				.then =>
 					this.p.is_liked = true
@@ -420,9 +420,9 @@
 			this.loading-context = true
 
 			// Get context
-			this.api 'posts/context' do
+			this.api('posts/context', {
 				post_id: this.p.reply_to_id
-			.then (context) =>
+			}).then((context) => {
 				this.context = context.reverse!
 				this.loading-context = false
 				this.update();
diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag
index 05cb1c565..43643f88c 100644
--- a/src/web/app/mobile/tags/post-form.tag
+++ b/src/web/app/mobile/tags/post-form.tag
@@ -220,8 +220,8 @@
 			this.refs.file.click();
 
 		this.select-file-from-drive = () => {
-			browser = document.body.appendChild document.createElement 'mk-drive-selector' 
-			browser = riot.mount browser, do
+			browser = document.body.appendChild(document.createElement('mk-drive-selector'));
+ 			browser = riot.mount browser, do
 				multiple: true
 			.0
 			browser.on('selected', (files) => {
@@ -260,12 +260,12 @@
 				then this.files.map (f) -> f.id
 				else undefined
 
-			this.api 'posts/create' do
+			this.api('posts/create', {
 				text: this.refs.text.value
 				media_ids: files
 				reply_to_id: if this.opts.reply? then this.opts.reply.id else undefined
 				poll: if this.poll then this.refs.poll.get! else undefined
-			.then (data) =>
+			}).then((data) => {
 				this.trigger('post');
 				this.unmount();
 			.catch (err) =>
diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag
index caa0af4be..83c4b9cfb 100644
--- a/src/web/app/mobile/tags/search-posts.tag
+++ b/src/web/app/mobile/tags/search-posts.tag
@@ -16,15 +16,15 @@
 		this.with-media = this.opts.with-media
 
 		this.init = new Promise (res, rej) =>
-			this.api 'posts/search' do
+			this.api('posts/search', {
 				query: @query
-			.then (posts) =>
+			}).then((posts) => {
 				res posts
 				this.trigger('loaded');
 
 		this.more = () => {
 			@offset += @max
-			this.api 'posts/search' do
+			this.api('posts/search', {
 				query: @query
 				max: @max
 				offset: @offset
diff --git a/src/web/app/mobile/tags/timeline-post.tag b/src/web/app/mobile/tags/timeline-post.tag
index 2d6a6a1fa..a19fca7fc 100644
--- a/src/web/app/mobile/tags/timeline-post.tag
+++ b/src/web/app/mobile/tags/timeline-post.tag
@@ -3,10 +3,19 @@
 		<mk-timeline-post-sub post={ p.reply_to }></mk-timeline-post-sub>
 	</div>
 	<div class="repost" if={ isRepost }>
-		<p><a class="avatar-anchor" href={ CONFIG.url + '/' + post.user.username }><img class="avatar" src={ post.user.avatar_url + '?thumbnail&size=64' } alt="avatar"/></a><i class="fa fa-retweet"></i><a class="name" href={ CONFIG.url + '/' + post.user.username }>{ post.user.name }</a>がRepost</p>
+		<p>
+			<a class="avatar-anchor" href={ CONFIG.url + '/' + post.user.username }>
+				<img class="avatar" src={ post.user.avatar_url + '?thumbnail&size=64' } alt="avatar"/>
+			</a>
+			<i class="fa fa-retweet"></i>
+			<a class="name" href={ CONFIG.url + '/' + post.user.username }>{ post.user.name }</a>がRepost
+		</p>
 		<mk-time time={ post.created_at }></mk-time>
 	</div>
-	<article><a class="avatar-anchor" href={ CONFIG.url + '/' + p.user.username }><img class="avatar" src={ p.user.avatar_url + '?thumbnail&size=96' } alt="avatar"/></a>
+	<article>
+		<a class="avatar-anchor" href={ CONFIG.url + '/' + p.user.username }>
+			<img class="avatar" src={ p.user.avatar_url + '?thumbnail&size=96' } alt="avatar"/>
+		</a>
 		<div class="main">
 			<header>
 				<a class="name" href={ CONFIG.url + '/' + p.user.username }>{ p.user.name }</a>
@@ -289,59 +298,67 @@
 		this.mixin('api');
 		this.mixin('text');
 		this.mixin('get-post-summary');
-		this.mixin('open-post-form');
+		this.mixin('openPostForm');
 
-		this.post = this.opts.post
-		this.is-repost = this.post.repost? and !this.post.text?
-		this.p = if @is-repost then this.post.repost else this.post
-		this.summary = @get-post-summary this.p
+		this.post = this.opts.post;
+		this.isRepost = this.post.repost != null && this.post.text == null;
+		this.p = this.isRepost ? this.post.repost : this.post;
+		this.summary = this.getPostSummary(this.p);
 		this.url = CONFIG.url + '/' + this.p.user.username + '/' + this.p.id
 
 		this.on('mount', () => {
-			if this.p.text?
-				tokens = if this.p._highlight?
-					then @analyze this.p._highlight
-					else @analyze this.p.text
+			if (this.p.text) {
+				const tokens = this.analyze(this.p.text);
 
-				this.refs.text.innerHTML = this.refs.text.innerHTML.replace '<p class="dummy"></p>' if this.p._highlight?
-					then @compile tokens, true, false
-					else @compile tokens
+				this.refs.text.innerHTML = this.refs.text.innerHTML.replace('<p class="dummy"></p>', this.compile(tokens));
 
-				this.refs.text.children.forEach (e) =>
-					if e.tag-name == 'MK-URL' 
-						riot.mount e
+				this.refs.text.children.forEach(e => {
+					if (e.tagName == 'MK-URL') riot.mount(e);
+				});
 
 				// URLをプレビュー
 				tokens
-					.filter (t) -> t.type == 'link' 
-					.map (t) =>
-						this.preview = this.refs.text.appendChild document.createElement 'mk-url-preview' 
-						riot.mount this.preview, do
-							url: t.content
+				.filter(t => t.type == 'link')
+				.map(t => {
+					riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
+						url: t.content
+					});
+				});
+			}
+		});
 
 		this.reply = () => {
-			@open-post-form do
+			this.openPostForm({
 				reply: this.p
+			});
+		};
 
 		this.repost = () => {
-			text = window.prompt '「' + @summary + '」をRepost'
-			if text?
-				this.api 'posts/create' do
-					repost_id: this.p.id
-					text: if text == '' then undefined else text
+			const text = window.prompt(`「${this.summary}」をRepost`);
+			if (text) {
+				this.api('posts/create', {
+					repost_id: this.p.id,
+					text: text == '' ? undefined : text
+				});
+			}
+		};
 
 		this.like = () => {
-			if this.p.is_liked
-				this.api 'posts/likes/delete' do
+			if (this.p.is_liked)
+				this.api('posts/likes/delete', {
 					post_id: this.p.id
-				.then =>
-					this.p.is_liked = false
+				}).then(() => {
+					this.p.is_liked = false;
 					this.update();
-			else
-				this.api 'posts/likes/create' do
+				});
+			} else {
+				this.api('posts/likes/create', {
 					post_id: this.p.id
-				.then =>
-					this.p.is_liked = true
+				}).then(() => {
+					this.p.is_liked = true;
 					this.update();
+				});
+			}
+		};
 	</script>
 </mk-timeline-post>
diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag
index 3887045e8..06571e40e 100644
--- a/src/web/app/mobile/tags/timeline.tag
+++ b/src/web/app/mobile/tags/timeline.tag
@@ -80,7 +80,7 @@
 		this.can-fetch-more = true
 
 		this.on('mount', () => {
-			this.opts.init.then (posts) =>
+			this.opts.init}).then((posts) => {
 				this.init = false
 				@set-posts posts
 
@@ -95,7 +95,7 @@
 			if @init or @fetching or this.posts.length == 0 then return
 			this.fetching = true
 			this.update();
-			this.opts.more!.then (posts) =>
+			this.opts.more!}).then((posts) => {
 				this.fetching = false
 				this.prepend-posts posts
 
diff --git a/src/web/app/mobile/tags/ui-header.tag b/src/web/app/mobile/tags/ui-header.tag
index 6a7ec8ec5..5cf2560d5 100644
--- a/src/web/app/mobile/tags/ui-header.tag
+++ b/src/web/app/mobile/tags/ui-header.tag
@@ -89,7 +89,7 @@
 	</style>
 	<script>
 		this.mixin('ui');
-		this.mixin('open-post-form');
+		this.mixin('openPostForm');
 
 		this.on('mount', () => {
 			this.opts.ready!
@@ -99,6 +99,6 @@
 				this.refs.title.innerHTML = title
 
 		this.post = () => {
-			@open-post-form!
+			this.openPostForm!
 	</script>
 </mk-ui-header>
diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag
index 348c88b77..ca6ac3f55 100644
--- a/src/web/app/mobile/tags/ui.tag
+++ b/src/web/app/mobile/tags/ui.tag
@@ -44,8 +44,8 @@
 			this.refs.nav.root.style.display = if @is-drawer-opening then 'block' else 'none' 
 
 		this.on-stream-notification = (notification) => {
-			el = document.body.appendChild document.createElement 'mk-notify' 
-			riot.mount el, do
+			el = document.body.appendChild(document.createElement('mk-notify'));
+ 			riot.mount el, do
 				notification: notification
 	</script>
 </mk-ui>
diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag
index cdde081dc..eecf09cab 100644
--- a/src/web/app/mobile/tags/user-followers.tag
+++ b/src/web/app/mobile/tags/user-followers.tag
@@ -11,7 +11,7 @@
 		this.user = this.opts.user
 
 		this.fetch = (iknow, limit, cursor, cb) => {
-			this.api 'users/followers' do
+			this.api('users/followers', {
 				user_id: this.user.id
 				iknow: iknow
 				limit: limit
diff --git a/src/web/app/mobile/tags/user-following.tag b/src/web/app/mobile/tags/user-following.tag
index 37ee0ee39..b214789aa 100644
--- a/src/web/app/mobile/tags/user-following.tag
+++ b/src/web/app/mobile/tags/user-following.tag
@@ -11,7 +11,7 @@
 		this.user = this.opts.user
 
 		this.fetch = (iknow, limit, cursor, cb) => {
-			this.api 'users/following' do
+			this.api('users/following', {
 				user_id: this.user.id
 				iknow: iknow
 				limit: limit
diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag
index 80311924f..2d3716b84 100644
--- a/src/web/app/mobile/tags/user-timeline.tag
+++ b/src/web/app/mobile/tags/user-timeline.tag
@@ -15,15 +15,15 @@
 		this.with-media = this.opts.with-media
 
 		this.init = new Promise (res, rej) =>
-			this.api 'users/posts' do
+			this.api('users/posts', {
 				user_id: this.user.id
 				with_media: @with-media
-			.then (posts) =>
+			}).then((posts) => {
 				res posts
 				this.trigger('loaded');
 
 		this.more = () => {
-			this.api 'users/posts' do
+			this.api('users/posts', {
 				user_id: this.user.id
 				with_media: @with-media
 				max_id: this.refs.timeline.tail!.id
diff --git a/src/web/app/mobile/tags/user.tag b/src/web/app/mobile/tags/user.tag
index 660b08879..9d95e9914 100644
--- a/src/web/app/mobile/tags/user.tag
+++ b/src/web/app/mobile/tags/user.tag
@@ -3,20 +3,43 @@
 		<header>
 			<div class="banner" style={ user.banner_url ? 'background-image: url(' + user.banner_url + '?thumbnail&size=1024)' : '' }></div>
 			<div class="body">
-				<div class="top"><a class="avatar"><img src={ user.avatar_url + '?thumbnail&size=160' } alt="avatar"/></a>
+				<div class="top">
+					<a class="avatar">
+						<img src={ user.avatar_url + '?thumbnail&size=160' } alt="avatar"/>
+					</a>
 					<mk-follow-button if={ SIGNIN && I.id != user.id } user={ user }></mk-follow-button>
 				</div>
 				<div class="title">
-					<h1>{ user.name }</h1><span class="username">@{ user.username }</span><span class="followed" if={ user.is_followed }>フォローされています</span>
+					<h1>{ user.name }</h1>
+					<span class="username">@{ user.username }</span>
+					<span class="followed" if={ user.is_followed }>フォローされています</span>
 				</div>
 				<div class="bio">{ user.bio }</div>
 				<div class="info">
-					<p class="location" if={ user.location }><i class="fa fa-map-marker"></i>{ user.location }</p>
-					<p class="birthday" if={ user.birthday }><i class="fa fa-birthday-cake"></i>{ user.birthday.replace('-', '年').replace('-', '月') + '日' } ({ age(user.birthday) }歳)</p>
+					<p class="location" if={ user.location }>
+						<i class="fa fa-map-marker"></i>{ user.location }
+					</p>
+					<p class="birthday" if={ user.birthday }>
+						<i class="fa fa-birthday-cake"></i>{ user.birthday.replace('-', '年').replace('-', '月') + '日' } ({ age(user.birthday) }歳)
+					</p>
+				</div>
+				<div class="friends">
+					<a href="{ user.username }/following">
+						<b>{ user.following_count }</b>
+						<i>フォロー</i>
+					</a>
+					<a href="{ user.username }/followers">
+						<b>{ user.followers_count }</b>
+						<i>フォロワー</i>
+					</a>
 				</div>
-				<div class="friends"><a href="{ user.username }/following"><b>{ user.following_count }</b><i>フォロー</i></a><a href="{ user.username }/followers"><b>{ user.followers_count }</b><i>フォロワー</i></a></div>
 			</div>
-			<nav><a data-is-active={ page == 'posts' } onclick={ goPosts }>投稿</a><a data-is-active={ page == 'media' } onclick={ goMedia }>メディア</a><a data-is-active={ page == 'graphs' } onclick={ goGraphs }>グラフ</a><a data-is-active={ page == 'likes' } onclick={ goLikes }>いいね</a></nav>
+			<nav>
+				<a data-is-active={ page == 'posts' } onclick={ go.bind(null, 'posts') }>投稿</a>
+				<a data-is-active={ page == 'media' } onclick={ go.bind(null, 'media') }>メディア</a>
+				<a data-is-active={ page == 'graphs' } onclick={ go.bind(null, 'graphs') }>グラフ</a>
+				<a data-is-active={ page == 'likes' } onclick={ go.bind(null, 'likes') }>いいね</a>
+			</nav>
 		</header>
 		<div class="body">
 			<mk-user-timeline if={ page == 'posts' } user={ user }></mk-user-timeline>
@@ -154,38 +177,30 @@
 
 	</style>
 	<script>
-		this.age = require 's-age' 
+		this.age = require('s-age');
 
 		this.mixin('i');
 		this.mixin('api');
 
-		this.username = this.opts.user
-		this.page = if this.opts.page? then this.opts.page else 'posts' 
-		this.fetching = true
+		this.username = this.opts.user;
+		this.page = this.opts.page ? this.opts.page : 'posts';
+		this.fetching = true;
 
 		this.on('mount', () => {
-			this.api 'users/show' do
+			this.api('users/show', {
 				username: this.username
-			.then (user) =>
-				this.fetching = false
-				this.user = user
-				this.trigger 'loaded' user
+			}).then(user => {
+				this.fetching = false;
+				this.user = user;
+				this.trigger('loaded', user);
 				this.update();
+			});
+		});
 
-		this.go-posts = () => {
-			this.page = 'posts' 
-			this.update();
-
-		this.go-media = () => {
-			this.page = 'media' 
-			this.update();
-
-		this.go-graphs = () => {
-			this.page = 'graphs' 
-			this.update();
-
-		this.go-likes = () => {
-			this.page = 'likes' 
-			this.update();
+		this.go = page => {
+			this.update({
+				page: page
+			});
+		};
 	</script>
 </mk-user>

From 3a39a36bedad75a134127823bbd12af2907ee24a Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 16:27:24 +0900
Subject: [PATCH 13/32] wip

---
 src/web/app/common/tags/messaging/room.tag    |  2 +-
 src/web/app/desktop/tags/pages/home.tag       |  6 +--
 src/web/app/desktop/tags/user-timeline.tag    |  6 +--
 src/web/app/mobile/tags/drive-selector.tag    | 15 +++++---
 src/web/app/mobile/tags/page/drive.tag        | 37 +++++++++++--------
 src/web/app/mobile/tags/page/entrance.tag     | 20 ++++++----
 .../app/mobile/tags/page/entrance/signup.tag  |  4 --
 src/web/app/mobile/tags/page/home.tag         | 34 ++++++++++-------
 .../app/mobile/tags/page/messaging-room.tag   | 15 +++++---
 src/web/app/mobile/tags/page/messaging.tag    |  9 +++--
 src/web/app/mobile/tags/page/new-post.tag     |  5 ---
 .../app/mobile/tags/page/notifications.tag    |  4 +-
 src/web/app/mobile/tags/page/post.tag         |  7 +++-
 src/web/app/mobile/tags/page/search.tag       |  7 ++--
 src/web/app/mobile/tags/page/settings.tag     |  3 +-
 src/web/app/mobile/tags/page/settings/api.tag |  3 +-
 .../tags/page/settings/authorized-apps.tag    |  3 +-
 .../app/mobile/tags/page/settings/signin.tag  |  3 +-
 .../app/mobile/tags/page/settings/twitter.tag |  3 +-
 .../app/mobile/tags/page/user-followers.tag   | 20 +++++-----
 .../app/mobile/tags/page/user-following.tag   | 20 +++++-----
 src/web/app/mobile/tags/page/user.tag         | 10 +++--
 22 files changed, 136 insertions(+), 100 deletions(-)

diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index f8088470e..8b1220e29 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -226,7 +226,7 @@
 			, 4000ms
 		};
 
-		this.on-visibilitychange = () => {
+		this.onVisibilitychange = () => {
 			if document.hidden then return
 			@messages.forEach (message) =>
 				if message.user_id != this.I.id and not message.is_read
diff --git a/src/web/app/desktop/tags/pages/home.tag b/src/web/app/desktop/tags/pages/home.tag
index 4ed74a373..433137e9c 100644
--- a/src/web/app/desktop/tags/pages/home.tag
+++ b/src/web/app/desktop/tags/pages/home.tag
@@ -28,18 +28,18 @@
 			document.title = 'Misskey'
 			this.Progress.start();
 			this.stream.on 'post' this.on-stream-post
-			document.addEventListener 'visibilitychange' @window-on-visibilitychange, false
+			document.addEventListener 'visibilitychange' @window-onVisibilitychange, false
 
 		this.on('unmount', () => {
 			this.stream.off 'post' this.on-stream-post
-			document.removeEventListener 'visibilitychange' @window-on-visibilitychange
+			document.removeEventListener 'visibilitychange' @window-onVisibilitychange
 
 		this.on-stream-post = (post) => {
 			if document.hidden and post.user_id !== this.I.id
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
-		this.window-on-visibilitychange = () => {
+		this.window-onVisibilitychange = () => {
 			if !document.hidden
 				this.unread-count = 0
 				document.title = 'Misskey'
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index acced7fc3..bc2e1744e 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -59,7 +59,7 @@
 		this.mode = 'default' 
 
 		this.on('mount', () => {
-			document.addEventListener 'visibilitychange' @window-on-visibilitychange, false
+			document.addEventListener 'visibilitychange' @window-onVisibilitychange, false
 			document.addEventListener 'keydown' this.on-document-keydown
 			window.addEventListener 'scroll' this.on-scroll
 
@@ -71,7 +71,7 @@
 					this.trigger('loaded');
 
 		this.on('unmount', () => {
-			document.removeEventListener 'visibilitychange' @window-on-visibilitychange
+			document.removeEventListener 'visibilitychange' @window-onVisibilitychange
 			document.removeEventListener 'keydown' this.on-document-keydown
 			window.removeEventListener 'scroll' this.on-scroll
 
@@ -120,7 +120,7 @@
 				@unread-count++
 				document.title = '(' + @unread-count + ') ' + @get-post-summary post
 
-		this.window-on-visibilitychange = () => {
+		this.window-onVisibilitychange = () => {
 			if !document.hidden
 				this.unread-count = 0
 				document.title = 'Misskey'
diff --git a/src/web/app/mobile/tags/drive-selector.tag b/src/web/app/mobile/tags/drive-selector.tag
index 873c49154..753a2c3a9 100644
--- a/src/web/app/mobile/tags/drive-selector.tag
+++ b/src/web/app/mobile/tags/drive-selector.tag
@@ -56,19 +56,24 @@
 
 	</style>
 	<script>
-		this.files = []
+		this.files = [];
 
 		this.on('mount', () => {
-			this.refs.browser.on('change-selected', (files) => {
-				this.files = files
-				this.update();
+			this.refs.browser.on('change-selected', files => {
+				this.update({
+					files: files
+				});
+			});
+		});
 
 		this.cancel = () => {
 			this.trigger('canceled');
 			this.unmount();
+		};
 
 		this.ok = () => {
-			this.trigger 'selected' this.files
+			this.trigger('selected', this.files);
 			this.unmount();
+		};
 	</script>
 </mk-drive-selector>
diff --git a/src/web/app/mobile/tags/page/drive.tag b/src/web/app/mobile/tags/page/drive.tag
index c3e16a704..c4cc64261 100644
--- a/src/web/app/mobile/tags/page/drive.tag
+++ b/src/web/app/mobile/tags/page/drive.tag
@@ -5,57 +5,64 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('ui');
 		this.mixin('ui-progress');
 
 		this.on('mount', () => {
-			document.title = 'Misskey Drive'
+			document.title = 'Misskey Drive';
 			this.ui.trigger('title', '<i class="fa fa-cloud"></i>ドライブ');
 
 			this.refs.ui.refs.browser.on('begin-load', () => {
 				this.Progress.start();
+			});
 
 			this.refs.ui.refs.browser.on('loaded-mid', () => {
 				this.Progress.set(0.5);
+			});
 
 			this.refs.ui.refs.browser.on('loaded', () => {
 				this.Progress.done();
+			});
 
 			this.refs.ui.refs.browser.on('move-root', () => {
-				title = 'Misskey Drive'
+				const title = 'Misskey Drive';
 
 				// Rewrite URL
-				history.pushState null, title, '/i/drive'
+				history.pushState(null, title, '/i/drive');
 
-				document.title = title
+				document.title = title;
 				this.ui.trigger('title', '<i class="fa fa-cloud"></i>ドライブ');
+			});
 
 			this.refs.ui.refs.browser.on('open-folder', (folder, silent) => {
-				title = folder.name + ' | Misskey Drive'
+				const title = folder.name + ' | Misskey Drive';
 
-				if !silent
+				if (!silent) {
 					// Rewrite URL
-					history.pushState null, title, '/i/drive/folder/' + folder.id
+					history.pushState(null, title, '/i/drive/folder/' + folder.id);
+				}
 
-				document.title = title
+				document.title = title;
 				// TODO: escape html characters in folder.name
 				this.ui.trigger('title', '<i class="fa fa-folder-open"></i>' + folder.name);
+			});
 
 			this.refs.ui.refs.browser.on('open-file', (file, silent) => {
-				title = file.name + ' | Misskey Drive'
+				const title = file.name + ' | Misskey Drive';
 
-				if !silent
+				if (!silent) {
 					// Rewrite URL
-					history.pushState null, title, '/i/drive/file/' + file.id
+					history.pushState(null, title, '/i/drive/file/' + file.id);
+				}
 
-				document.title = title
+				document.title = title;
 				// TODO: escape html characters in file.name
 				this.ui.trigger('title', '<mk-file-type-icon class="icon"></mk-file-type-icon>' + file.name);
-				riot.mount 'mk-file-type-icon' do
+				riot.mount('mk-file-type-icon', {
 					type: file.type
-
+				});
+			});
 	</script>
 </mk-drive-page>
diff --git a/src/web/app/mobile/tags/page/entrance.tag b/src/web/app/mobile/tags/page/entrance.tag
index 1197d0578..452dff992 100644
--- a/src/web/app/mobile/tags/page/entrance.tag
+++ b/src/web/app/mobile/tags/page/entrance.tag
@@ -43,18 +43,24 @@
 
 	</style>
 	<script>
-		this.mode = 'signin' 
+		this.mode = 'signin';
 
 		this.signup = () => {
-			this.mode = 'signup' 
-			this.update();
+			this.update({
+				mode: 'signup'
+			});
+		};
 
 		this.signin = () => {
-			this.mode = 'signin' 
-			this.update();
+			this.update({
+				mode: 'signin'
+			});
+		};
 
 		this.introduction = () => {
-			this.mode = 'introduction' 
-			this.update();
+			this.update({
+				mode: 'introduction'
+			});
+		};
 	</script>
 </mk-entrance>
diff --git a/src/web/app/mobile/tags/page/entrance/signup.tag b/src/web/app/mobile/tags/page/entrance/signup.tag
index 520954388..c4b3ee9f3 100644
--- a/src/web/app/mobile/tags/page/entrance/signup.tag
+++ b/src/web/app/mobile/tags/page/entrance/signup.tag
@@ -34,9 +34,5 @@
 				> i
 					padding 14px
 
-			
-
-			
-
 	</style>
 </mk-entrance-signup>
diff --git a/src/web/app/mobile/tags/page/home.tag b/src/web/app/mobile/tags/page/home.tag
index ac00800a1..c93803fb0 100644
--- a/src/web/app/mobile/tags/page/home.tag
+++ b/src/web/app/mobile/tags/page/home.tag
@@ -5,7 +5,6 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('i');
@@ -14,7 +13,7 @@
 		this.mixin('stream');
 		this.mixin('get-post-summary');
 
-		this.unread-count = 0
+		this.unreadCount = 0;
 
 		this.on('mount', () => {
 			document.title = 'Misskey'
@@ -22,24 +21,31 @@
 
 			this.Progress.start();
 
-			this.stream.on 'post' this.on-stream-post
-			document.addEventListener 'visibilitychange' @window-on-visibilitychange, false
+			this.stream.on('post', this.onStreamPost);
+			document.addEventListener('visibilitychange', this.onVisibilitychange, false);
 
 			this.refs.ui.refs.home.on('loaded', () => {
 				this.Progress.done();
+			});
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'post' this.on-stream-post
-			document.removeEventListener 'visibilitychange' @window-on-visibilitychange
+			this.stream.off('post', this.onStreamPost);
+			document.removeEventListener('visibilitychange', this.onVisibilitychange);
+		});
 
-		this.on-stream-post = (post) => {
-			if document.hidden and post.user_id !== this.I.id
-				@unread-count++
-				document.title = '(' + @unread-count + ') ' + @get-post-summary post
+		this.onStreamPost = post => {
+			if (document.hidden && post.user_id !== this.I.id) {
+				this.unreadCount++;
+				document.title = `(${this.unreadCount}) ${this.getPostSummary(post)}`;
+			}
+		};
 
-		this.window-on-visibilitychange = () => {
-			if !document.hidden
-				this.unread-count = 0
-				document.title = 'Misskey'
+		this.onVisibilitychange = () => {
+			if (!document.hidden) {
+				this.unreadCount = 0;
+				document.title = 'Misskey';
+			}
+		};
 	</script>
 </mk-home-page>
diff --git a/src/web/app/mobile/tags/page/messaging-room.tag b/src/web/app/mobile/tags/page/messaging-room.tag
index 934a7f877..29657802a 100644
--- a/src/web/app/mobile/tags/page/messaging-room.tag
+++ b/src/web/app/mobile/tags/page/messaging-room.tag
@@ -10,18 +10,21 @@
 		this.mixin('api');
 		this.mixin('ui');
 
-		this.fetching = true
+		this.fetching = true;
 
 		this.on('mount', () => {
 			this.api('users/show', {
 				username: this.opts.username
 			}).then(user => {
-				this.fetching = false
-				this.user = user
-				this.update();
+				this.update({
+					fetching: false,
+					user: user
+				});
 
-				document.title = 'メッセージ: ' + user.name + ' | Misskey'
+				document.title = `メッセージ: ${user.name} | Misskey`;
 				// TODO: ユーザー名をエスケープ
-				this.ui.trigger('title', '<i class="fa fa-comments-o"></i>'); + user.name
+				this.ui.trigger('title', '<i class="fa fa-comments-o"></i>' + user.name);
+			});
+		});
 	</script>
 </mk-messaging-room-page>
diff --git a/src/web/app/mobile/tags/page/messaging.tag b/src/web/app/mobile/tags/page/messaging.tag
index 78a2ca991..fd94cbfa4 100644
--- a/src/web/app/mobile/tags/page/messaging.tag
+++ b/src/web/app/mobile/tags/page/messaging.tag
@@ -11,11 +11,12 @@
 		this.mixin('page');
 
 		this.on('mount', () => {
-			document.title = 'Misskey | メッセージ'
+			document.title = 'Misskey | メッセージ';
 			this.ui.trigger('title', '<i class="fa fa-comments-o"></i>メッセージ');
 
-			this.refs.ui.refs.index.on('navigate-user', (user) => {
-				this.page '/i/messaging/' + user.username
-
+			this.refs.ui.refs.index.on('navigate-user', user => {
+				this.page('/i/messaging/' + user.username);
+			});
+		});
 	</script>
 </mk-messaging-page>
diff --git a/src/web/app/mobile/tags/page/new-post.tag b/src/web/app/mobile/tags/page/new-post.tag
index e323f0d95..3ba549c8d 100644
--- a/src/web/app/mobile/tags/page/new-post.tag
+++ b/src/web/app/mobile/tags/page/new-post.tag
@@ -3,10 +3,5 @@
 	<style>
 		:scope
 			display block
-
-			
-
-			
-
 	</style>
 </mk-new-post-page>
diff --git a/src/web/app/mobile/tags/page/notifications.tag b/src/web/app/mobile/tags/page/notifications.tag
index b33386fb8..1d35d79ed 100644
--- a/src/web/app/mobile/tags/page/notifications.tag
+++ b/src/web/app/mobile/tags/page/notifications.tag
@@ -12,12 +12,14 @@
 		this.mixin('ui-progress');
 
 		this.on('mount', () => {
-			document.title = 'Misskey | 通知'
+			document.title = 'Misskey | 通知';
 			this.ui.trigger('title', '<i class="fa fa-bell-o"></i>通知');
 
 			this.Progress.start();
 
 			this.refs.ui.refs.notifications.on('loaded', () => {
 				this.Progress.done();
+			});
+		});
 	</script>
 </mk-notifications-page>
diff --git a/src/web/app/mobile/tags/page/post.tag b/src/web/app/mobile/tags/page/post.tag
index 69a24c552..2c4eba37a 100644
--- a/src/web/app/mobile/tags/page/post.tag
+++ b/src/web/app/mobile/tags/page/post.tag
@@ -21,18 +21,21 @@
 		this.mixin('ui');
 		this.mixin('ui-progress');
 
-		this.post = this.opts.post
+		this.post = this.opts.post;
 
 		this.on('mount', () => {
-			document.title = 'Misskey'
+			document.title = 'Misskey';
 			this.ui.trigger('title', '<i class="fa fa-sticky-note-o"></i>投稿');
 
 			this.Progress.start();
 
 			this.refs.ui.refs.post.on('post-fetched', () => {
 				this.Progress.set(0.5);
+			});
 
 			this.refs.ui.refs.post.on('loaded', () => {
 				this.Progress.done();
+			});
+		});
 	</script>
 </mk-post-page>
diff --git a/src/web/app/mobile/tags/page/search.tag b/src/web/app/mobile/tags/page/search.tag
index 4dde50ab8..fbf741f2e 100644
--- a/src/web/app/mobile/tags/page/search.tag
+++ b/src/web/app/mobile/tags/page/search.tag
@@ -5,20 +5,21 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('ui');
 		this.mixin('ui-progress');
 
 		this.on('mount', () => {
-			document.title = '検索: ' + this.opts.query + ' | Misskey'
+			document.title = `検索: ${this.opts.query} | Misskey`
 			// TODO: クエリをHTMLエスケープ
-			this.ui.trigger('title', '<i class="fa fa-search"></i>'); + this.opts.query
+			this.ui.trigger('title', '<i class="fa fa-search"></i>' + this.opts.query);
 
 			this.Progress.start();
 
 			this.refs.ui.refs.search.on('loaded', () => {
 				this.Progress.done();
+			});
+		});
 	</script>
 </mk-search-page>
diff --git a/src/web/app/mobile/tags/page/settings.tag b/src/web/app/mobile/tags/page/settings.tag
index 5e06a302e..59974e8cb 100644
--- a/src/web/app/mobile/tags/page/settings.tag
+++ b/src/web/app/mobile/tags/page/settings.tag
@@ -16,7 +16,8 @@
 		this.mixin('ui');
 
 		this.on('mount', () => {
-			document.title = 'Misskey | 設定'
+			document.title = 'Misskey | 設定';
 			this.ui.trigger('title', '<i class="fa fa-cog"></i>設定');
+		});
 	</script>
 </mk-settings-page>
diff --git a/src/web/app/mobile/tags/page/settings/api.tag b/src/web/app/mobile/tags/page/settings/api.tag
index 039792c0a..e4f954f51 100644
--- a/src/web/app/mobile/tags/page/settings/api.tag
+++ b/src/web/app/mobile/tags/page/settings/api.tag
@@ -10,7 +10,8 @@
 		this.mixin('ui');
 
 		this.on('mount', () => {
-			document.title = 'Misskey | API'
+			document.title = 'Misskey | API';
 			this.ui.trigger('title', '<i class="fa fa-key"></i>API');
+		});
 	</script>
 </mk-api-info-page>
diff --git a/src/web/app/mobile/tags/page/settings/authorized-apps.tag b/src/web/app/mobile/tags/page/settings/authorized-apps.tag
index 1415f11d0..84904c91e 100644
--- a/src/web/app/mobile/tags/page/settings/authorized-apps.tag
+++ b/src/web/app/mobile/tags/page/settings/authorized-apps.tag
@@ -10,7 +10,8 @@
 		this.mixin('ui');
 
 		this.on('mount', () => {
-			document.title = 'Misskey | アプリケーション'
+			document.title = 'Misskey | アプリケーション';
 			this.ui.trigger('title', '<i class="fa fa-puzzle-piece"></i>アプリケーション');
+		});
 	</script>
 </mk-authorized-apps-page>
diff --git a/src/web/app/mobile/tags/page/settings/signin.tag b/src/web/app/mobile/tags/page/settings/signin.tag
index 092cd6441..874cdf485 100644
--- a/src/web/app/mobile/tags/page/settings/signin.tag
+++ b/src/web/app/mobile/tags/page/settings/signin.tag
@@ -10,7 +10,8 @@
 		this.mixin('ui');
 
 		this.on('mount', () => {
-			document.title = 'Misskey | ログイン履歴'
+			document.title = 'Misskey | ログイン履歴';
 			this.ui.trigger('title', '<i class="fa fa-sign-in"></i>ログイン履歴');
+		});
 	</script>
 </mk-signin-history-page>
diff --git a/src/web/app/mobile/tags/page/settings/twitter.tag b/src/web/app/mobile/tags/page/settings/twitter.tag
index 87550efe2..2026ab7da 100644
--- a/src/web/app/mobile/tags/page/settings/twitter.tag
+++ b/src/web/app/mobile/tags/page/settings/twitter.tag
@@ -10,7 +10,8 @@
 		this.mixin('ui');
 
 		this.on('mount', () => {
-			document.title = 'Misskey | Twitter連携'
+			document.title = 'Misskey | Twitter連携';
 			this.ui.trigger('title', '<i class="fa fa-twitter"></i>Twitter連携');
+		});
 	</script>
 </mk-twitter-setting-page>
diff --git a/src/web/app/mobile/tags/page/user-followers.tag b/src/web/app/mobile/tags/page/user-followers.tag
index 75a2c5d27..249897be2 100644
--- a/src/web/app/mobile/tags/page/user-followers.tag
+++ b/src/web/app/mobile/tags/page/user-followers.tag
@@ -5,15 +5,14 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('ui');
 		this.mixin('ui-progress');
 		this.mixin('api');
 
-		this.fetching = true
-		this.user = null
+		this.fetching = true;
+		this.user = null;
 
 		this.on('mount', () => {
 			this.Progress.start();
@@ -21,16 +20,19 @@
 			this.api('users/show', {
 				username: this.opts.user
 			}).then(user => {
-				this.user = user
-				this.fetching = false
+				this.update({
+					fetching: false,
+					user: user
+				});
 
-				document.title = user.name + 'のフォロワー | Misskey'
+				document.title = user.name + 'のフォロワー | Misskey';
 				// TODO: ユーザー名をエスケープ
-				this.ui.trigger('title', '<img src="'); + user.avatar_url + '?thumbnail&size=64">' + user.name + 'のフォロワー'
-
-				this.update();
+				this.ui.trigger('title', '<img src="' + user.avatar_url + '?thumbnail&size=64">' + user.name + 'のフォロワー');
 
 				this.refs.ui.refs.list.on('loaded', () => {
 					this.Progress.done();
+				});
+			});
+		});
 	</script>
 </mk-user-followers-page>
diff --git a/src/web/app/mobile/tags/page/user-following.tag b/src/web/app/mobile/tags/page/user-following.tag
index 44a054e82..a682715a0 100644
--- a/src/web/app/mobile/tags/page/user-following.tag
+++ b/src/web/app/mobile/tags/page/user-following.tag
@@ -5,15 +5,14 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('ui');
 		this.mixin('ui-progress');
 		this.mixin('api');
 
-		this.fetching = true
-		this.user = null
+		this.fetching = true;
+		this.user = null;
 
 		this.on('mount', () => {
 			this.Progress.start();
@@ -21,16 +20,19 @@
 			this.api('users/show', {
 				username: this.opts.user
 			}).then(user => {
-				this.user = user
-				this.fetching = false
+				this.update({
+					fetching: false,
+					user: user
+				});
 
-				document.title = user.name + 'のフォロー | Misskey'
+				document.title = user.name + 'のフォロー | Misskey';
 				// TODO: ユーザー名をエスケープ
-				this.ui.trigger('title', '<img src="'); + user.avatar_url + '?thumbnail&size=64">' + user.name + 'のフォロー'
-
-				this.update();
+				this.ui.trigger('title', '<img src="' + user.avatar_url + '?thumbnail&size=64">' + user.name + 'のフォロー');
 
 				this.refs.ui.refs.list.on('loaded', () => {
 					this.Progress.done();
+				});
+			});
+		});
 	</script>
 </mk-user-following-page>
diff --git a/src/web/app/mobile/tags/page/user.tag b/src/web/app/mobile/tags/page/user.tag
index 4215ca2c3..2a0e48426 100644
--- a/src/web/app/mobile/tags/page/user.tag
+++ b/src/web/app/mobile/tags/page/user.tag
@@ -11,15 +11,17 @@
 		this.mixin('ui');
 		this.mixin('ui-progress');
 
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.on('mount', () => {
 			this.Progress.start();
 
-			this.refs.ui.refs.user.on('loaded', (user) => {
+			this.refs.ui.refs.user.on('loaded', user => {
 				this.Progress.done();
-				document.title = user.name + ' | Misskey'
+				document.title = user.name + ' | Misskey';
 				// TODO: ユーザー名をエスケープ
-				this.ui.trigger('title', '<i class="fa fa-user"></i>'); + user.name
+				this.ui.trigger('title', '<i class="fa fa-user"></i>' + user.name);
+			});
+		});
 	</script>
 </mk-user-page>

From 2a3a5d4b509e527d1871b6a993f49b29c734c268 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 20 Feb 2017 20:13:42 +0900
Subject: [PATCH 14/32] wip

---
 src/web/app/auth/tags/form.tag                |   4 +-
 src/web/app/auth/tags/index.tag               |   2 +-
 src/web/app/common/scripts/contains.js        |   8 +
 src/web/app/common/tags/signin.tag            |   2 +-
 src/web/app/common/tags/signup.tag            |   4 +-
 src/web/app/desktop/tags/analog-clock.tag     | 156 ++++++++---------
 .../desktop/tags/autocomplete-suggestion.tag  | 164 ++++++++++--------
 .../app/desktop/tags/big-follow-button.tag    |   8 +-
 src/web/app/desktop/tags/contextmenu.tag      |  60 +++----
 src/web/app/desktop/tags/dialog.tag           |  79 +++++----
 src/web/app/desktop/tags/drive/browser.tag    |   4 +-
 .../desktop/tags/drive/file-contextmenu.tag   |   2 +-
 .../desktop/tags/drive/folder-contextmenu.tag |   2 +-
 src/web/app/desktop/tags/drive/folder.tag     |   4 +-
 src/web/app/desktop/tags/drive/nav-folder.tag |   4 +-
 src/web/app/desktop/tags/ellipsis-icon.tag    |   4 -
 src/web/app/desktop/tags/follow-button.tag    |   8 +-
 src/web/app/desktop/tags/go-top.tag           |  14 --
 src/web/app/desktop/tags/images-viewer.tag    |   2 +-
 src/web/app/desktop/tags/index.js             |   1 -
 src/web/app/desktop/tags/input-dialog.tag     |  42 +++--
 src/web/app/desktop/tags/post-detail-sub.tag  |   4 +-
 src/web/app/desktop/tags/post-detail.tag      |   4 +-
 src/web/app/desktop/tags/post-form.tag        |   2 +-
 src/web/app/desktop/tags/repost-form.tag      |   4 +-
 src/web/app/desktop/tags/search-posts.tag     |   4 +-
 src/web/app/desktop/tags/sub-post-content.tag |  24 ++-
 src/web/app/desktop/tags/timeline-post.tag    | 103 +++++++----
 src/web/app/desktop/tags/window.tag           |   2 +-
 src/web/app/dev/tags/new-app-form.tag         |   2 +-
 src/web/app/mobile/tags/drive/file-viewer.tag |   4 +-
 src/web/app/mobile/tags/follow-button.tag     |   8 +-
 src/web/app/mobile/tags/post-detail.tag       |   4 +-
 src/web/app/mobile/tags/search-posts.tag      |  20 +--
 src/web/app/mobile/tags/user-timeline.tag     |  10 +-
 35 files changed, 402 insertions(+), 367 deletions(-)
 create mode 100644 src/web/app/common/scripts/contains.js
 delete mode 100644 src/web/app/desktop/tags/go-top.tag

diff --git a/src/web/app/auth/tags/form.tag b/src/web/app/auth/tags/form.tag
index 21a9a7404..619c71065 100644
--- a/src/web/app/auth/tags/form.tag
+++ b/src/web/app/auth/tags/form.tag
@@ -114,13 +114,13 @@
 		this.cancel = () => {
 			this.api('auth/deny', {
 				token: @session.token
-			.then =>
+			}).then(() => {
 				this.trigger('denied');
 
 		this.accept = () => {
 			this.api('auth/accept', {
 				token: @session.token
-			.then =>
+			}).then(() => {
 				this.trigger('accepted');
 	</script>
 </mk-form>
diff --git a/src/web/app/auth/tags/index.tag b/src/web/app/auth/tags/index.tag
index 13abf0790..e52aeed4d 100644
--- a/src/web/app/auth/tags/index.tag
+++ b/src/web/app/auth/tags/index.tag
@@ -110,7 +110,7 @@
 				if @session.app.is_authorized
 					this.api('auth/accept', {
 						token: @session.token
-					.then =>
+					}).then(() => {
 						@accepted!
 				else
 					this.state = 'waiting' 
diff --git a/src/web/app/common/scripts/contains.js b/src/web/app/common/scripts/contains.js
new file mode 100644
index 000000000..fe7366619
--- /dev/null
+++ b/src/web/app/common/scripts/contains.js
@@ -0,0 +1,8 @@
+module.exports = function(parent, child) {
+	let node = child.parentNode;
+	while (node) {
+		if (node == parent) return true;
+		node = node.parentNode;
+	}
+	return false;
+}
diff --git a/src/web/app/common/tags/signin.tag b/src/web/app/common/tags/signin.tag
index 7b297b7b8..e2b873682 100644
--- a/src/web/app/common/tags/signin.tag
+++ b/src/web/app/common/tags/signin.tag
@@ -126,7 +126,7 @@
 			this.api('signin', {
 				username: this.refs.username.value
 				password: this.refs.password.value
-			.then =>
+			}).then(() => {
 				location.reload();
 			.catch =>
 				alert 'something happened'
diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag
index 7646f8c86..39d4522e7 100644
--- a/src/web/app/common/tags/signup.tag
+++ b/src/web/app/common/tags/signup.tag
@@ -277,11 +277,11 @@
 				username: username,
 				password: password,
 				'g-recaptcha-response': grecaptcha.getResponse()
-			.then =>
+			}).then(() => {
 				this.api('signin', {
 					username: username
 					password: password
-				.then =>
+				}).then(() => {
 					location.href = CONFIG.url
 			.catch =>
 				alert '何らかの原因によりアカウントの作成に失敗しました。再度お試しください。'
diff --git a/src/web/app/desktop/tags/analog-clock.tag b/src/web/app/desktop/tags/analog-clock.tag
index ec627ec65..4ac6d2281 100644
--- a/src/web/app/desktop/tags/analog-clock.tag
+++ b/src/web/app/desktop/tags/analog-clock.tag
@@ -6,100 +6,92 @@
 				display block
 				width 256px
 				height 256px
-
 	</style>
 	<script>
+		class Vec2 {
+			constructor(x, y) {
+				this.x = x;
+				this.y = y;
+			}
+		}
+
 		this.on('mount', () => {
-			@draw!
-			this.clock = setInterval @draw, 1000ms
+			this.draw()
+			this.clock = setInterval(this.draw, 1000);
+		});
 
 		this.on('unmount', () => {
-			clearInterval @clock
+			clearInterval(this.clock);
+		});
 
 		this.draw = () => {
 			const now = new Date();
-			s = now.get-seconds!
-			m = now.getMinutes()
-			h = now.getHours()
+			const s = now.getSeconds();
+			const m = now.getMinutes();
+			const h = now.getHours();
 
-			vec2 = (x, y) ->
-				this.x = x
-				this.y = y
+			const ctx = this.refs.canvas.getContext('2d');
+			const canvW = this.refs.canvas.width;
+			const canvH = this.refs.canvas.height;
+			ctx.clearRect(0, 0, canvW, canvH);
 
-			ctx = this.refs.canvas.get-context '2d' 
-			canv-w = this.refs.canvas.width
-			canv-h = this.refs.canvas.height
-			ctx.clear-rect 0, 0, canv-w, canv-h
+			{ // 背景
+				const center = Math.min((canvW / 2), (canvH / 2));
+				const lineStart =    center * 0.90;
+				const shortLineEnd = center * 0.87;
+				const longLineEnd =  center * 0.84;
+				for (let i = 0; i < 60; i++) {
+					const angle = Math.PI * i / 30;
+					const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
+					ctx.beginPath();
+					ctx.lineWidth = 1;
+					ctx.moveTo((canv-w / 2) + uv.x * lineStart, (canv-h / 2) + uv.y * lineStart);
+					if (i % 5 == 0) {
+						ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)';
+						ctx.lineTo((canv-w / 2) + uv.x * longLineEnd, (canv-h / 2) + uv.y * longLineEnd);
+					} else {
+						ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
+						ctx.lineTo((canv-w / 2) + uv.x * shortLineEnd, (canv-h / 2) + uv.y * shortLineEnd);
+					}
+					ctx.stroke();
+				}
+			}
 
-			// 背景
-			center = (Math.min (canv-w / 2), (canv-h / 2))
-			line-start = center * 0.90
-			line-end-short = center * 0.87
-			line-end-long = center * 0.84
-			for i from 0 to 59 by 1
-				angle = Math.PI * i / 30
-				uv = new vec2 (Math.sin angle), (-Math.cos angle)
-				ctx.begin-path!
-				ctx.line-width = 1
-				ctx.move-to do
-					(canv-w / 2) + uv.x * line-start
-					(canv-h / 2) + uv.y * line-start
-				if i % 5 == 0
-					ctx.stroke-style = 'rgba(255, 255, 255, 0.2)'
-					ctx.line-to do
-						(canv-w / 2) + uv.x * line-end-long
-						(canv-h / 2) + uv.y * line-end-long
-				else
-					ctx.stroke-style = 'rgba(255, 255, 255, 0.1)'
-					ctx.line-to do
-						(canv-w / 2) + uv.x * line-end-short
-						(canv-h / 2) + uv.y * line-end-short
-				ctx.stroke!
+			{ // 分
+				const angle = Math.PI * (m + s / 60) / 30;
+				const length = Math.min(canvW, canvH) / 2.6;
+				const uv = new vec2(Math.sin(angle), -Math.cos(angle));
+				ctx.beginPath();
+				ctx.strokeStyle = '#ffffff';
+				ctx.lineWidth = 2;
+				ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
+				ctx.lineTo(canvW / 2 + uv.x * length,     canvH / 2 + uv.y * length);
+				ctx.stroke();
+			}
 
-			// 分
-			angle = Math.PI * (m + s / 60) / 30
-			length = (Math.min canv-w, canv-h) / 2.6
-			uv = new vec2 (Math.sin angle), (-Math.cos angle)
-			ctx.begin-path!
-			ctx.stroke-style = '#ffffff' 
-			ctx.line-width = 2
-			ctx.move-to do
-				(canv-w / 2) - uv.x * length / 5
-				(canv-h / 2) - uv.y * length / 5
-			ctx.line-to do
-				(canv-w / 2) + uv.x * length
-				(canv-h / 2) + uv.y * length
-			ctx.stroke!
+			{ // 時
+				const angle = Math.PI * (h % 12 + m / 60) / 6;
+				const length = Math.min(canvW, canvH) / 4;
+				const uv = new vec2(Math.sin(angle), -Math.cos(angle));
+				ctx.beginPath();
+				ctx.strokeStyle = CONFIG.themeColor;
+				ctx.lineWidth = 2;
+				ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
+				ctx.lineTo(canvW / 2 + uv.x * length,     canvH / 2 + uv.y * length);
+				ctx.stroke();
+			}
 
-			// 時
-			angle = Math.PI * (h % 12 + m / 60) / 6
-			length = (Math.min canv-w, canv-h) / 4
-			uv = new vec2 (Math.sin angle), (-Math.cos angle)
-			ctx.begin-path!
-			#ctx.stroke-style = '#ffffff' 
-			ctx.stroke-style = CONFIG.theme-color
-			ctx.line-width = 2
-			ctx.move-to do
-				(canv-w / 2) - uv.x * length / 5
-				(canv-h / 2) - uv.y * length / 5
-			ctx.line-to do
-				(canv-w / 2) + uv.x * length
-				(canv-h / 2) + uv.y * length
-			ctx.stroke!
-
-			// 秒
-			angle = Math.PI * s / 30
-			length = (Math.min canv-w, canv-h) / 2.6
-			uv = new vec2 (Math.sin angle), (-Math.cos angle)
-			ctx.begin-path!
-			ctx.stroke-style = 'rgba(255, 255, 255, 0.5)'
-			ctx.line-width = 1
-			ctx.move-to do
-				(canv-w / 2) - uv.x * length / 5
-				(canv-h / 2) - uv.y * length / 5
-			ctx.line-to do
-				(canv-w / 2) + uv.x * length
-				(canv-h / 2) + uv.y * length
-			ctx.stroke!
+			{ // 秒
+				const angle = Math.PI * s / 30;
+				const length = Math.min(canvW, canvH) / 2.6;
+				const uv = new vec2(Math.sin(angle), -Math.cos(angle));
+				ctx.beginPath();
+				ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
+				ctx.lineWidth = 1;
+				ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
+				ctx.lineTo(canvW / 2 + uv.x * length,     canvH / 2 + uv.y * length);
+				ctx.stroke();
+			}
+		};
 	</script>
 </mk-analog-clock>
diff --git a/src/web/app/desktop/tags/autocomplete-suggestion.tag b/src/web/app/desktop/tags/autocomplete-suggestion.tag
index 40f5f5759..c7cc29dc1 100644
--- a/src/web/app/desktop/tags/autocomplete-suggestion.tag
+++ b/src/web/app/desktop/tags/autocomplete-suggestion.tag
@@ -80,108 +80,118 @@
 
 	</style>
 	<script>
+		const contains = require('../../common/scripts/contains');
+
 		this.mixin('api');
 
-		this.q = this.opts.q
-		this.textarea = this.opts.textarea
-		this.loading = true
-		this.users = []
-		this.select = -1
+		this.q = this.opts.q;
+		this.textarea = this.opts.textarea;
+		this.fetching = true;
+		this.users = [];
+		this.select = -1;
 
 		this.on('mount', () => {
-			@textarea.addEventListener 'keydown' this.on-keydown
+			this.textarea.addEventListener('keydown', this.onKeydown);
 
-			all = document.query-selector-all 'body *'
-			Array.prototype.forEach.call all, (el) =>
-				el.addEventListener 'mousedown' @mousedown
+			document.querySelectorAll('body *').forEach(el => {
+				el.addEventListener('mousedown', this.mousedown);
+			});
 
 			this.api('users/search_by_username', {
-				query: @q
-				limit: 30users
-			}).then((users) => {
-				this.users = users
-				this.loading = false
-				this.update();
-			.catch (err) =>
-				console.error err
+				query: this.q,
+				limit: 30
+			}).then(users => {
+				this.update({
+					fetching: false,
+					users: users
+				});
+			});
+		});
 
 		this.on('unmount', () => {
-			@textarea.removeEventListener 'keydown' this.on-keydown
+			this.textarea.removeEventListener('keydown', this.onKeydown);
 
-			all = document.query-selector-all 'body *'
-			Array.prototype.forEach.call all, (el) =>
-				el.removeEventListener 'mousedown' @mousedown
+			document.querySelectorAll('body *').forEach(el => {
+				el.removeEventListener('mousedown', this.mousedown);
+			});
+		});
 
-		this.mousedown = (e) => {
-			if (!contains this.root, e.target) and (this.root != e.target)
-				@close();
+		this.mousedown = e => {
+			if (!contains(this.root, e.target) && (this.root != e.target)) this.close();
+		};
 
-		this.on-click = (e) => {
-			@complete e.item
+		this.onClick = e => {
+			this.complete(e.item);
+		};
 
-		this.on-keydown = (e) => {
-			key = e.which
-			switch (key)
-				| 10, 13 => // Key[ENTER]
-					if @select != -1
-						e.preventDefault();
-						e.stopPropagation();
-						@complete this.users[@select]
-					else
-						@close();
-				| 27 => // Key[ESC]
-					e.preventDefault();
-					e.stopPropagation();
-					@close();
-				| 38 => // Key[↑]
-					if @select != -1
-						e.preventDefault();
-						e.stopPropagation();
-						@select-prev!
-					else
-						@close();
-				| 9, 40 => // Key[TAB] or Key[↓]
-					e.preventDefault();
-					e.stopPropagation();
-					@select-next!
-				| _ =>
-					@close();
+		this.onKeydown = e => {
+			const cancel = () => {
+				e.preventDefault();
+				e.stopPropagation();
+			};
 
-		this.select-next = () => {
-			@select++
+			switch (e.which) {
+				case 10: // [ENTER]
+				case 13: // [ENTER]
+					if (this.select !== -1) {
+						cancel();
+						this.complete(this.users[this.select]);
+					} else {
+						this.close();
+					}
+					break;
 
-			if @select >= this.users.length
-				this.select = 0
+				case 27: // [ESC]
+					cancel();
+					this.close();
+					break;
 
-			@apply-select!
+				case 38: // [↑]
+					if (this.select !== -1) {
+						cancel();
+						this.selectPrev();
+					} else {
+						this.close();
+					}
+					break;
 
-		this.select-prev = () => {
-			@select--
+				case 9: // [TAB]
+				case 40: // [↓]
+					cancel();
+					this.selectNext();
+					break;
 
-			if @select < 0
-				this.select = this.users.length - 1
+				default:
+					this.close();
+			}
+		};
 
-			@apply-select!
+		this.selectNext = () => {
+			if (++this.select >= this.users.length) this.select = 0;
+			this.applySelect();
+		};
 
-		this.apply-select = () => {
-			this.refs.users.children.forEach (el) =>
-				el.remove-attribute 'data-selected' 
+		this.selectPrev = () => {
+			if (--this.select < 0) this.select = this.users.length - 1;
+			this.applySelect();
+		};
 
-			this.refs.users.children[@select].setAttribute 'data-selected' \true
-			this.refs.users.children[@select].focus();
+		this.applySelect = () => {
+			this.refs.users.children.forEach(el => {
+				el.removeAttribute('data-selected');
+			});
 
-		this.complete = (user) => {
-			this.opts.complete user
+			this.refs.users.children[this.select].setAttribute('data-selected', 'true');
+			this.refs.users.children[this.select].focus();
+		};
+
+		this.complete = user => {
+			this.opts.complete(user);
+		};
 
 		this.close = () => {
 			this.opts.close();
+		};
 
-		function contains(parent, child)
-			node = child.parentNode
-			while node?
-				if node == parent
-					return true
-				node = node.parentNode
-			return false
 	</script>
 </mk-autocomplete-suggestion>
diff --git a/src/web/app/desktop/tags/big-follow-button.tag b/src/web/app/desktop/tags/big-follow-button.tag
index ba607c837..309e6ce8e 100644
--- a/src/web/app/desktop/tags/big-follow-button.tag
+++ b/src/web/app/desktop/tags/big-follow-button.tag
@@ -106,21 +106,21 @@
 			if this.user.is_following
 				this.api('following/delete', {
 					user_id: this.user.id
-				.then =>
+				}).then(() => {
 					this.user.is_following = false
 				.catch (err) ->
 					console.error err
-				.then =>
+				}).then(() => {
 					this.wait = false
 					this.update();
 			else
 				this.api('following/create', {
 					user_id: this.user.id
-				.then =>
+				}).then(() => {
 					this.user.is_following = true
 				.catch (err) ->
 					console.error err
-				.then =>
+				}).then(() => {
 					this.wait = false
 					this.update();
 	</script>
diff --git a/src/web/app/desktop/tags/contextmenu.tag b/src/web/app/desktop/tags/contextmenu.tag
index 92c8b71a2..8df11c381 100644
--- a/src/web/app/desktop/tags/contextmenu.tag
+++ b/src/web/app/desktop/tags/contextmenu.tag
@@ -1,4 +1,5 @@
-<mk-contextmenu><yield />
+<mk-contextmenu>
+	<yield />
 	<style>
 		:scope
 			$width = 240px
@@ -94,46 +95,45 @@
 
 	</style>
 	<script>
-		this.root.addEventListener 'contextmenu' (e) =>
+		const contains = require('../../common/scripts/contains');
+
+		this.root.addEventListener('contextmenu', e => {
 			e.preventDefault();
+		});
 
-		this.mousedown = (e) => {
+		this.mousedown = e => {
 			e.preventDefault();
-			if (!contains this.root, e.target) and (this.root != e.target)
-				@close();
-			return false
+			if (!contains(this.root, e.target) && (this.root != e.target)) this.close();
+			return false;
+		};
 
-		this.open = (pos) => {
-			all = document.query-selector-all 'body *'
-			Array.prototype.forEach.call all, (el) =>
-				el.addEventListener 'mousedown' @mousedown
-			this.root.style.display = 'block' 
-			this.root.style.left = pos.x + 'px' 
-			this.root.style.top = pos.y + 'px' 
+		this.open = pos => {
+			document.querySelectorAll('body *').forEach(el => {
+				el.addEventListener('mousedown', this.mousedown);
+			});
 
-			Velocity(this.root, 'finish' true
-			Velocity(this.root, { opacity: 0 } 0ms
+			this.root.style.display = 'block';
+			this.root.style.left = pos.x + 'px';
+			this.root.style.top = pos.y + 'px';
+
+			Velocity(this.root, 'finish', true);
+			Velocity(this.root, { opacity: 0 }, 0);
 			Velocity(this.root, {
 				opacity: 1
 			}, {
-				queue: false
-				duration: 100ms
-				easing: 'linear' 
-			}
+				queue: false,
+				duration: 100,
+				easing: 'linear'
+			});
+		};
 
 		this.close = () => {
-			all = document.query-selector-all 'body *'
-			Array.prototype.forEach.call all, (el) =>
-				el.removeEventListener 'mousedown' @mousedown
+			document.querySelectorAll('body *').forEach(el => {
+				el.removeEventListener('mousedown', this.mousedown);
+			});
+
 			this.trigger('closed');
 			this.unmount();
-
-		function contains(parent, child)
-			node = child.parentNode
-			while (node != null)
-				if (node == parent)
-					return true
-				node = node.parentNode
-			return false
+		};
 	</script>
 </mk-contextmenu>
diff --git a/src/web/app/desktop/tags/dialog.tag b/src/web/app/desktop/tags/dialog.tag
index 61a40e7b3..c0df0b330 100644
--- a/src/web/app/desktop/tags/dialog.tag
+++ b/src/web/app/desktop/tags/dialog.tag
@@ -79,69 +79,72 @@
 
 	</style>
 	<script>
-		this.can-through = if opts.can-through? then opts.can-through else true
-		this.opts.buttons.forEach (button) =>
-			button._onclick = =>
-				if button.onclick?
-					button.onclick();
-				@close();
+		this.canThrough = opts.canThrough != null ? opts.canThrough : true;
+		this.opts.buttons.forEach(button => {
+			button._onclick = () => {
+				if (button.onclick) button.onclick();
+				this.close();
+			};
+		});
 
 		this.on('mount', () => {
-			this.refs.header.innerHTML = this.opts.title
-			this.refs.body.innerHTML = this.opts.text
+			this.refs.header.innerHTML = this.opts.title;
+			this.refs.body.innerHTML = this.opts.text;
 
-			this.refs.bg.style.pointer-events = 'auto' 
-			Velocity(this.refs.bg, 'finish' true
+			this.refs.bg.style.pointerEvents = 'auto';
+			Velocity(this.refs.bg, 'finish', true);
 			Velocity(this.refs.bg, {
 				opacity: 1
 			}, {
-				queue: false
-				duration: 100ms
-				easing: 'linear' 
-			}
+				queue: false,
+				duration: 100,
+				easing: 'linear'
+			});
 
 			Velocity(this.refs.main, {
-				opacity: 0
+				opacity: 0,
 				scale: 1.2
 			}, {
 				duration: 0
-			}
+			});
 			Velocity(this.refs.main, {
-				opacity: 1
+				opacity: 1,
 				scale: 1
 			}, {
-				duration: 300ms
+				duration: 300,
 				easing: [ 0, 0.5, 0.5, 1 ]
-			}
+			});
+		});
 
 		this.close = () => {
-			this.refs.bg.style.pointer-events = 'none' 
-			Velocity(this.refs.bg, 'finish' true
+			this.refs.bg.style.pointerEvents = 'none';
+			Velocity(this.refs.bg, 'finish', true);
 			Velocity(this.refs.bg, {
 				opacity: 0
 			}, {
-				queue: false
-				duration: 300ms
+				queue: false,
+				duration: 300,
 				easing: 'linear' 
-			}
+			});
 
-			this.refs.main.style.pointer-events = 'none' 
-			Velocity(this.refs.main, 'finish' true
+			this.refs.main.style.pointerEvents = 'none';
+			Velocity(this.refs.main, 'finish', true);
 			Velocity(this.refs.main, {
-				opacity: 0
+				opacity: 0,
 				scale: 0.8
 			}, {
-				queue: false
-				duration: 300ms
-				easing: [ 0.5, -0.5, 1, 0.5 ]
-				complete: =>
-					this.unmount();
-			}
+				queue: false,
+				duration: 300,
+				easing: [ 0.5, -0.5, 1, 0.5 ],
+				complete: () => this.unmount()
+			});
+		};
 
-		this.bg-click = () => {
-			if @can-through
-				if this.opts.on-through?
-					this.opts.on-through!
-				@close();
+		this.bgClick = () => {
+			if (this.canThrough) {
+				if (this.opts.onThrough) this.opts.onThrough();
+				this.close();
+			}
+		};
 	</script>
 </mk-dialog>
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index 13019dd16..51c26943a 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -408,7 +408,7 @@
 				this.api('drive/files/update', {
 					file_id: file
 					folder_id: if this.folder? then this.folder.id else null
-				.then =>
+				}).then(() => {
 					// something
 				.catch (err, text-status) =>
 					console.error err
@@ -425,7 +425,7 @@
 				this.api('drive/folders/update', {
 					folder_id: folder
 					parent_id: if this.folder? then this.folder.id else null
-				.then =>
+				}).then(() => {
 					// something
 				.catch (err) =>
 					if err == 'detected-circular-definition'
diff --git a/src/web/app/desktop/tags/drive/file-contextmenu.tag b/src/web/app/desktop/tags/drive/file-contextmenu.tag
index 9a615a902..933ae6db0 100644
--- a/src/web/app/desktop/tags/drive/file-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/file-contextmenu.tag
@@ -68,7 +68,7 @@
 			this.api('drive/files/update', {
 				file_id: this.file.id
 				name: name
-			.then =>
+			}).then(() => {
 				// something
 			.catch (err) =>
 				console.error err
diff --git a/src/web/app/desktop/tags/drive/folder-contextmenu.tag b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
index 833eff42e..582aa5e52 100644
--- a/src/web/app/desktop/tags/drive/folder-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
@@ -54,7 +54,7 @@
 			this.api('drive/folders/update', {
 				folder_id: this.folder.id
 				name: name
-			.then =>
+			}).then(() => {
 				// something
 			.catch (err) =>
 				console.error err
diff --git a/src/web/app/desktop/tags/drive/folder.tag b/src/web/app/desktop/tags/drive/folder.tag
index fff3c13eb..c9bc5d7f0 100644
--- a/src/web/app/desktop/tags/drive/folder.tag
+++ b/src/web/app/desktop/tags/drive/folder.tag
@@ -118,7 +118,7 @@
 				this.api('drive/files/update', {
 					file_id: file
 					folder_id: this.folder.id
-				.then =>
+				}).then(() => {
 					// something
 				.catch (err, text-status) =>
 					console.error err
@@ -133,7 +133,7 @@
 				this.api('drive/folders/update', {
 					folder_id: folder
 					parent_id: this.folder.id
-				.then =>
+				}).then(() => {
 					// something
 				.catch (err) =>
 					if err == 'detected-circular-definition'
diff --git a/src/web/app/desktop/tags/drive/nav-folder.tag b/src/web/app/desktop/tags/drive/nav-folder.tag
index 3f57fc129..b485ddb53 100644
--- a/src/web/app/desktop/tags/drive/nav-folder.tag
+++ b/src/web/app/desktop/tags/drive/nav-folder.tag
@@ -72,7 +72,7 @@
 				this.api('drive/files/update', {
 					file_id: file
 					folder_id: if this.folder? then this.folder.id else null
-				.then =>
+				}).then(() => {
 					// something
 				.catch (err, text-status) =>
 					console.error err
@@ -87,7 +87,7 @@
 				this.api('drive/folders/update', {
 					folder_id: folder
 					parent_id: if this.folder? then this.folder.id else null
-				.then =>
+				}).then(() => {
 					// something
 				.catch (err, text-status) =>
 					console.error err
diff --git a/src/web/app/desktop/tags/ellipsis-icon.tag b/src/web/app/desktop/tags/ellipsis-icon.tag
index 731c2525f..8462bfc4a 100644
--- a/src/web/app/desktop/tags/ellipsis-icon.tag
+++ b/src/web/app/desktop/tags/ellipsis-icon.tag
@@ -33,9 +33,5 @@
 				40%
 					transform scale(1)
 
-			
-
-			
-
 	</style>
 </mk-ellipsis-icon>
diff --git a/src/web/app/desktop/tags/follow-button.tag b/src/web/app/desktop/tags/follow-button.tag
index 7b5ab7d0e..64055a158 100644
--- a/src/web/app/desktop/tags/follow-button.tag
+++ b/src/web/app/desktop/tags/follow-button.tag
@@ -103,21 +103,21 @@
 			if this.user.is_following
 				this.api('following/delete', {
 					user_id: this.user.id
-				.then =>
+				}).then(() => {
 					this.user.is_following = false
 				.catch (err) ->
 					console.error err
-				.then =>
+				}).then(() => {
 					this.wait = false
 					this.update();
 			else
 				this.api('following/create', {
 					user_id: this.user.id
-				.then =>
+				}).then(() => {
 					this.user.is_following = true
 				.catch (err) ->
 					console.error err
-				.then =>
+				}).then(() => {
 					this.wait = false
 					this.update();
 	</script>
diff --git a/src/web/app/desktop/tags/go-top.tag b/src/web/app/desktop/tags/go-top.tag
deleted file mode 100644
index cb75c0480..000000000
--- a/src/web/app/desktop/tags/go-top.tag
+++ /dev/null
@@ -1,14 +0,0 @@
-<mk-go-top>
-	<button class="hidden" title="一番上へ"><i class="fa fa-angle-up"></i></button>
-	<script>
-		window.addEventListener 'load' this.on-scroll
-		window.addEventListener 'scroll' this.on-scroll
-		window.addEventListener 'resize' this.on-scroll
-
-		this.on-scroll = () => {
-			if $ window .scroll-top! > 500px
-				@remove-class 'hidden' 
-			else
-				@add-class 'hidden' 
-	</script>
-</mk-go-top>
diff --git a/src/web/app/desktop/tags/images-viewer.tag b/src/web/app/desktop/tags/images-viewer.tag
index 986debab4..8d10ec656 100644
--- a/src/web/app/desktop/tags/images-viewer.tag
+++ b/src/web/app/desktop/tags/images-viewer.tag
@@ -39,7 +39,7 @@
 
 		this.click = () => {
 			dialog = document.body.appendChild(document.createElement('mk-image-dialog'));
- 			riot.mount dialog, do
+			riot.mount dialog, do
 				image: @image
 	</script>
 </mk-images-viewer>
diff --git a/src/web/app/desktop/tags/index.js b/src/web/app/desktop/tags/index.js
index ed100ef75..a90e42211 100644
--- a/src/web/app/desktop/tags/index.js
+++ b/src/web/app/desktop/tags/index.js
@@ -16,7 +16,6 @@ require('./crop-window.tag');
 require('./settings.tag');
 require('./settings-window.tag');
 require('./analog-clock.tag');
-require('./go-top.tag');
 require('./ui-header.tag');
 require('./ui-header-account.tag');
 require('./ui-header-notifications.tag');
diff --git a/src/web/app/desktop/tags/input-dialog.tag b/src/web/app/desktop/tags/input-dialog.tag
index dbfd1cfc7..aa417f0a7 100644
--- a/src/web/app/desktop/tags/input-dialog.tag
+++ b/src/web/app/desktop/tags/input-dialog.tag
@@ -1,13 +1,17 @@
 <mk-input-dialog>
-	<mk-window ref="window" is-modal={ true } width={ '500px' }><yield to="header"><i class="fa fa-i-cursor"></i>{ parent.title }</yield>
-<yield to="content">
-		<div class="body">
-			<input ref="text" oninput={ parent.update } onkeydown={ parent.onKeydown } placeholder={ parent.placeholder }/>
-		</div>
-		<div class="action">
-			<button class="cancel" onclick={ parent.cancel }>キャンセル</button>
-			<button class="ok" disabled={ !parent.allowEmpty && refs.text.value.length == 0 } onclick={ parent.ok }>決定</button>
-		</div></yield>
+	<mk-window ref="window" is-modal={ true } width={ '500px' }>
+		<yield to="header">
+			<i class="fa fa-i-cursor"></i>{ parent.title }
+		</yield>
+		<yield to="content">
+			<div class="body">
+				<input ref="text" oninput={ parent.update } onkeydown={ parent.onKeydown } placeholder={ parent.placeholder }/>
+			</div>
+			<div class="action">
+				<button class="cancel" onclick={ parent.cancel }>キャンセル</button>
+				<button class="ok" disabled={ !parent.allowEmpty && refs.text.value.length == 0 } onclick={ parent.ok }>決定</button>
+			</div>
+		</yield>
 	</mk-window>
 	<style>
 		:scope
@@ -116,18 +120,17 @@
 
 	</style>
 	<script>
-		this.done = false
+		this.done = false;
 
-		this.title = this.opts.title
-		this.placeholder = this.opts.placeholder
-		this.default = this.opts.default
-		this.allow-empty = if this.opts.allow-empty? then this.opts.allow-empty else true
+		this.title = this.opts.title;
+		this.placeholder = this.opts.placeholder;
+		this.default = this.opts.default;
+		this.allowEmpty = this.opts.allowEmpty != null ? this.opts.allowEmpty : true;
 
 		this.on('mount', () => {
-			this.text = this.refs.window.refs.text
-			if @default?
-				@text.value = @default
-			@text.focus();
+			this.text = this.refs.window.refs.text;
+			if (this.default) this.text.value = this.default;
+			this.text.focus();
 
 			this.refs.window.on('closing', () => {
 				if @done
@@ -138,6 +141,7 @@
 
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
 
 		this.cancel = () => {
 			this.done = false
@@ -148,7 +152,7 @@
 			this.done = true
 			this.refs.window.close();
 
-		this.on-keydown = (e) => {
+		this.onKeydown = (e) => {
 			if e.which == 13 // Enter
 				e.preventDefault();
 				e.stopPropagation();
diff --git a/src/web/app/desktop/tags/post-detail-sub.tag b/src/web/app/desktop/tags/post-detail-sub.tag
index f5fec6f6a..24feda9be 100644
--- a/src/web/app/desktop/tags/post-detail-sub.tag
+++ b/src/web/app/desktop/tags/post-detail-sub.tag
@@ -127,13 +127,13 @@
 			if this.post.is_liked
 				this.api('posts/likes/delete', {
 					post_id: this.post.id
-				.then =>
+				}).then(() => {
 					this.post.is_liked = false
 					this.update();
 			else
 				this.api('posts/likes/create', {
 					post_id: this.post.id
-				.then =>
+				}).then(() => {
 					this.post.is_liked = true
 					this.update();
 	</script>
diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag
index 3b5671452..00426ea9b 100644
--- a/src/web/app/desktop/tags/post-detail.tag
+++ b/src/web/app/desktop/tags/post-detail.tag
@@ -412,13 +412,13 @@
 			if this.p.is_liked
 				this.api('posts/likes/delete', {
 					post_id: this.p.id
-				.then =>
+				}).then(() => {
 					this.p.is_liked = false
 					this.update();
 			else
 				this.api('posts/likes/create', {
 					post_id: this.p.id
-				.then =>
+				}).then(() => {
 					this.p.is_liked = true
 					this.update();
 
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index fe435c4e4..cb1693420 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -455,7 +455,7 @@
 			.catch (err) =>
 				console.error err
 				@notify '投稿できませんでした'
-			.then =>
+			}).then(() => {
 				this.wait = false
 				this.update();
 
diff --git a/src/web/app/desktop/tags/repost-form.tag b/src/web/app/desktop/tags/repost-form.tag
index c3e3e02df..7d309bf75 100644
--- a/src/web/app/desktop/tags/repost-form.tag
+++ b/src/web/app/desktop/tags/repost-form.tag
@@ -127,14 +127,14 @@
 			this.wait = true
 			this.api('posts/create', {
 				repost_id: this.opts.post.id
-				text: if @quote then this.refs.text.value else undefined
+				text: if this.quote then this.refs.text.value else undefined
 			}).then((data) => {
 				this.trigger('posted');
 				@notify 'Repostしました!'
 			.catch (err) =>
 				console.error err
 				@notify 'Repostできませんでした'
-			.then =>
+			}).then(() => {
 				this.wait = false
 				this.update();
 
diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag
index bad055eb0..248b8cc87 100644
--- a/src/web/app/desktop/tags/search-posts.tag
+++ b/src/web/app/desktop/tags/search-posts.tag
@@ -42,7 +42,7 @@
 			window.addEventListener 'scroll' this.on-scroll
 
 			this.api('posts/search', {
-				query: @query
+				query: this.query
 			}).then((posts) => {
 				this.is-loading = false
 				this.is-empty = posts.length == 0
@@ -68,7 +68,7 @@
 			this.more-loading = true
 			this.update();
 			this.api('posts/search', {
-				query: @query
+				query: this.query
 				page: this.page + 1
 			}).then((posts) => {
 				this.more-loading = false
diff --git a/src/web/app/desktop/tags/sub-post-content.tag b/src/web/app/desktop/tags/sub-post-content.tag
index 8d4a06b49..e0509ab7d 100644
--- a/src/web/app/desktop/tags/sub-post-content.tag
+++ b/src/web/app/desktop/tags/sub-post-content.tag
@@ -1,5 +1,11 @@
 <mk-sub-post-content>
-	<div class="body"><a class="reply" if={ post.reply_to_id }><i class="fa fa-reply"></i></a><span ref="text"></span><a class="quote" if={ post.repost_id } href={ '/post:' + post.repost_id }>RP: ...</a></div>
+	<div class="body">
+		<a class="reply" if={ post.reply_to_id }>
+			<i class="fa fa-reply"></i>
+		</a>
+		<span ref="text"></span>
+		<a class="quote" if={ post.repost_id } href={ '/post:' + post.repost_id }>RP: ...</a>
+	</div>
 	<details if={ post.media }>
 		<summary>({ post.media.length }つのメディア)</summary>
 		<mk-images-viewer images={ post.media }></mk-images-viewer>
@@ -31,15 +37,17 @@
 		this.mixin('text');
 		this.mixin('user-preview');
 
-		this.post = this.opts.post
+		this.post = this.opts.post;
 
 		this.on('mount', () => {
-			if this.post.text?
-				tokens = @analyze this.post.text
-				this.refs.text.innerHTML = @compile tokens, false
+			if (this.post.text) {
+				const tokens = this.analyze(this.post.text);
+				this.refs.text.innerHTML = this.compile(tokens, false);
 
-				this.refs.text.children.forEach (e) =>
-					if e.tag-name == 'MK-URL' 
-						riot.mount e
+				this.refs.text.children.forEach(e => {
+					if (e.tagName == 'MK-URL') riot.mount(e);
+				});
+			}
+		});
 	</script>
 </mk-sub-post-content>
diff --git a/src/web/app/desktop/tags/timeline-post.tag b/src/web/app/desktop/tags/timeline-post.tag
index 5b656f812..440d5d9f4 100644
--- a/src/web/app/desktop/tags/timeline-post.tag
+++ b/src/web/app/desktop/tags/timeline-post.tag
@@ -324,7 +324,7 @@
 		this.mixin('NotImplementedException');
 
 		this.post = this.opts.post;
-		this.isRepost = this.post.repost != null && this.post.text == null;
+		this.isRepost = this.post.repost && this.post.text == null;
 		this.p = this.isRepost ? this.post.repost : this.post;
 
 		this.title = this.dateStringify(this.p.created_at);
@@ -354,58 +354,87 @@
 		});
 
 		this.reply = () => {
-			form = document.body.appendChild(document.createElement('mk-post-form-window'));
- 			riot.mount form, do
+			riot.mount(document.body.appendChild(document.createElement('mk-post-form-window')), {
 				reply: this.p
+			});
+		};
 
 		this.repost = () => {
-			form = document.body.appendChild(document.createElement('mk-repost-form-window'));
- 			riot.mount form, do
+			riot.mount(document.body.appendChild(document.createElement('mk-repost-form-window')), {
 				post: this.p
+			});
+		};
 
 		this.like = () => {
-			if this.p.is_liked
+			if (this.p.is_liked) {
 				this.api('posts/likes/delete', {
 					post_id: this.p.id
-				.then =>
-					this.p.is_liked = false
+				}).then(() => {
+					this.p.is_liked = false;
 					this.update();
-			else
+				});
+			} else {
 				this.api('posts/likes/create', {
 					post_id: this.p.id
-				.then =>
-					this.p.is_liked = true
+				}).then(() => {
+					this.p.is_liked = true;
 					this.update();
+				});
+			}
+		};
 
-		this.toggle-detail = () => {
-			this.is-detail-opened = !@is-detail-opened
-			this.update();
+		this.toggleDetail = () => {
+			this.update({
+				isDetailOpened: !this.isDetailOpened
+			});
+		};
 
-		this.on-key-down = (e) => {
-			should-be-cancel = true
-			switch
-			| e.which == 38 or e.which == 74 or (e.which == 9 and e.shift-key) => // ↑, j or Shift+Tab
-				focus this.root, (e) -> e.previousElementSibling
-			| e.which == 40 or e.which == 75 or e.which == 9 => // ↓, k or Tab
-				focus this.root, (e) -> e.nextElementSibling
-			| e.which == 81 or e.which == 69 => // q or e
-				@repost!
-			| e.which == 70 or e.which == 76 => // f or l
-				@like!
-			| e.which == 82 => // r
-				@reply!
-			| _ =>
-				should-be-cancel = false
+		this.onKeyDown = e => {
+			let shouldBeCancel = true;
 
-			if should-be-cancel
-				e.preventDefault();
+			switch (true) {
+				case e.which == 38: // [↑]
+				case e.which == 74: // [j]
+				case e.which == 9 && e.shiftKey: // [Shift] + [Tab]
+					focus(this.root, e => e.previousElementSibling);
+					break;
 
-		function focus(el, fn)
-			target = fn el
-			if target?
-				if target.has-attribute 'tabindex' 
+				case e.which == 40: // [↓]
+				case e.which == 75: // [k]
+				case e.which == 9: // [Tab]
+					focus(this.root, e => e.nextElementSibling);
+					break;
+
+				case e.which == 81: // [q]
+				case e.which == 69: // [e]
+					this.repost();
+					break;
+
+				case e.which == 70: // [f]
+				case e.which == 76: // [l]
+					this.like();
+					break;
+
+				case e.which == 82: // [r]
+					this.reply();
+					break;
+				
+				default:
+					shouldBeCancel = false;
+			}
+
+			if (shouldBeCancel) e.preventDefault();
+		};
+
+		function focus(el, fn) {
+			const target = fn(el);
+			if (target) {
+				if (target.hasAttribute('tabindex')) {
 					target.focus();
-				else
-					focus target, fn
+				} else {
+					focus(target, fn);
+				}
+			}
+		}
 	</script>
 </mk-timeline-post>
diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index 33bb244fa..bd9df8823 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -501,7 +501,7 @@
 		this.ondragover = (e) => {
 			e.dataTransfer.dropEffect = 'none' 
 
-		this.on-keydown = (e) => {
+		this.onKeydown = (e) => {
 			if e.which == 27 // Esc
 				if @can-close
 					e.preventDefault();
diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag
index 6be1c5448..c75eec37d 100644
--- a/src/web/app/dev/tags/new-app-form.tag
+++ b/src/web/app/dev/tags/new-app-form.tag
@@ -233,7 +233,7 @@
 				description: description
 				callback_url: cb
 				permission: permission.join ',' 
-			.then =>
+			}).then(() => {
 				location.href = '/apps'
 			.catch =>
 				alert 'アプリの作成に失敗しました。再度お試しください。'
diff --git a/src/web/app/mobile/tags/drive/file-viewer.tag b/src/web/app/mobile/tags/drive/file-viewer.tag
index 5f2c5f61f..e91a451c0 100644
--- a/src/web/app/mobile/tags/drive/file-viewer.tag
+++ b/src/web/app/mobile/tags/drive/file-viewer.tag
@@ -192,9 +192,9 @@
 			name = window.prompt '名前を変更' this.file.name
 			if name? and name != '' and name != this.file.name
 				this.api('drive/files/update', {
-					file_id: this.file.id
+					file_id: this.file.id,
 					name: name
-				.then =>
+				}).then(() => {
 					this.parent.cf this.file, true
 
 	</script>
diff --git a/src/web/app/mobile/tags/follow-button.tag b/src/web/app/mobile/tags/follow-button.tag
index ecd0dc594..43fcc3499 100644
--- a/src/web/app/mobile/tags/follow-button.tag
+++ b/src/web/app/mobile/tags/follow-button.tag
@@ -84,21 +84,21 @@
 			if this.user.is_following
 				this.api('following/delete', {
 					user_id: this.user.id
-				.then =>
+				}).then(() => {
 					this.user.is_following = false
 				.catch (err) ->
 					console.error err
-				.then =>
+				}).then(() => {
 					this.wait = false
 					this.update();
 			else
 				this.api('following/create', {
 					user_id: this.user.id
-				.then =>
+				}).then(() => {
 					this.user.is_following = true
 				.catch (err) ->
 					console.error err
-				.then =>
+				}).then(() => {
 					this.wait = false
 					this.update();
 	</script>
diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag
index 61983a159..2b4bef1da 100644
--- a/src/web/app/mobile/tags/post-detail.tag
+++ b/src/web/app/mobile/tags/post-detail.tag
@@ -406,13 +406,13 @@
 			if this.p.is_liked
 				this.api('posts/likes/delete', {
 					post_id: this.p.id
-				.then =>
+				}).then(() => {
 					this.p.is_liked = false
 					this.update();
 			else
 				this.api('posts/likes/create', {
 					post_id: this.p.id
-				.then =>
+				}).then(() => {
 					this.p.is_liked = true
 					this.update();
 
diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag
index 83c4b9cfb..2dbb162d7 100644
--- a/src/web/app/mobile/tags/search-posts.tag
+++ b/src/web/app/mobile/tags/search-posts.tag
@@ -9,24 +9,24 @@
 	<script>
 		this.mixin('api');
 
-		this.max = 30
-		this.offset = 0
+		this.max = 30;
+		this.offset = 0;
 
-		this.query = this.opts.query
-		this.with-media = this.opts.with-media
+		this.query = this.opts.query;
+		this.withMedia = this.opts.withMedia;
 
 		this.init = new Promise (res, rej) =>
 			this.api('posts/search', {
-				query: @query
-			}).then((posts) => {
+				query: this.query
+			}).then(posts => {
 				res posts
 				this.trigger('loaded');
 
 		this.more = () => {
-			@offset += @max
+			this.offset += this.max;
 			this.api('posts/search', {
-				query: @query
-				max: @max
-				offset: @offset
+				query: this.query
+				max: this.max
+				offset: this.offset
 	</script>
 </mk-search-posts>
diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag
index 2d3716b84..71fb1ac27 100644
--- a/src/web/app/mobile/tags/user-timeline.tag
+++ b/src/web/app/mobile/tags/user-timeline.tag
@@ -11,21 +11,21 @@
 	<script>
 		this.mixin('api');
 
-		this.user = this.opts.user
-		this.with-media = this.opts.with-media
+		this.user = this.opts.user;
+		this.withMedia = this.opts.withMedia;
 
 		this.init = new Promise (res, rej) =>
 			this.api('users/posts', {
 				user_id: this.user.id
-				with_media: @with-media
-			}).then((posts) => {
+				with_media: @withMedia
+			}).then(posts => {
 				res posts
 				this.trigger('loaded');
 
 		this.more = () => {
 			this.api('users/posts', {
 				user_id: this.user.id
-				with_media: @with-media
+				with_media: this.withMedia
 				max_id: this.refs.timeline.tail!.id
 	</script>
 </mk-user-timeline>

From beb04e918ebe39a3cf97eeae7d44a209030915ea Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 00:44:18 +0900
Subject: [PATCH 15/32] wip

---
 .../app/desktop/tags/ui-header-account.tag    |  66 +--
 src/web/app/desktop/tags/ui-header-clock.tag  |  39 +-
 src/web/app/desktop/tags/ui-header-nav.tag    | 198 ++++----
 .../desktop/tags/ui-header-notifications.tag  |  50 +-
 src/web/app/desktop/tags/ui-header-search.tag |   5 +-
 src/web/app/desktop/tags/window.tag           | 460 +++++++++---------
 6 files changed, 431 insertions(+), 387 deletions(-)

diff --git a/src/web/app/desktop/tags/ui-header-account.tag b/src/web/app/desktop/tags/ui-header-account.tag
index 334b69e21..c035529f7 100644
--- a/src/web/app/desktop/tags/ui-header-account.tag
+++ b/src/web/app/desktop/tags/ui-header-account.tag
@@ -159,54 +159,54 @@
 
 	</style>
 	<script>
+		const contains = require('../../common/scripts/contains');
+
 		this.mixin('i');
 		this.mixin('signout');
 
-		this.is-open = false
+		this.isOpen = false;
 
 		this.on('before-unmount', () => {
-			@close();
+			this.close();
+		});
 
 		this.toggle = () => {
-			if @is-open
-				@close();
-			else
-				@open!
+			this.isOpen ? this.close() : this.open();
+		};
 
 		this.open = () => {
-			this.is-open = true
-			this.update();
-			all = document.query-selector-all 'body *'
-			Array.prototype.forEach.call all, (el) =>
-				el.addEventListener 'mousedown' @mousedown
+			this.update({
+				isOpen: true
+			});
+			document.querySelectorAll('body *').forEach(el => {
+				el.addEventListener('mousedown', this.mousedown);
+			});
+		};
 
 		this.close = () => {
-			this.is-open = false
-			this.update();
-			all = document.query-selector-all 'body *'
-			Array.prototype.forEach.call all, (el) =>
-				el.removeEventListener 'mousedown' @mousedown
+			this.update({
+				isOpen: false
+			});
+			document.querySelectorAll('body *').forEach(el => {
+				el.removeEventListener('mousedown', this.mousedown);
+			});
+		};
 
-		this.mousedown = (e) => {
+		this.mousedown = e => {
 			e.preventDefault();
-			if (!contains this.root, e.target) and (this.root != e.target)
-				@close();
-			return false
+			if (!contains(this.root, e.target) && this.root != e.target) this.close();
+			return false;
+		};
 
 		this.drive = () => {
-			@close();
-			riot.mount document.body.appendChild(document.createElement('mk-drive-browser-window'));
- 
+			this.close();
+			riot.mount(document.body.appendChild(document.createElement('mk-drive-browser-window')));
+		};
+
 		this.settings = () => {
-			@close();
-			riot.mount document.body.appendChild(document.createElement('mk-settings-window'));
- 
-		function contains(parent, child)
-			node = child.parentNode
-			while node?
-				if node == parent
-					return true
-				node = node.parentNode
-			return false
+			this.close();
+			riot.mount(document.body.appendChild(document.createElement('mk-settings-window')));
+		};
+
 	</script>
 </mk-ui-header-account>
diff --git a/src/web/app/desktop/tags/ui-header-clock.tag b/src/web/app/desktop/tags/ui-header-clock.tag
index 74336b460..ce41083fc 100644
--- a/src/web/app/desktop/tags/ui-header-clock.tag
+++ b/src/web/app/desktop/tags/ui-header-clock.tag
@@ -1,6 +1,9 @@
 <mk-ui-header-clock>
 	<div class="header">
-		<time ref="time"></time>
+		<time ref="time">
+			<span class="yyyymmdd">{ yyyy }/{ mm }/{ dd }</span>
+			<span class="hhnn">{ hh }<span style="visibility:{ now.getSeconds() % 2 == 0 ? 'visible' : 'hidden' }">:</span>{ nn }</span>
+		</time>
 	</div>
 	<div class="content">
 		<mk-analog-clock></mk-analog-clock>
@@ -13,7 +16,7 @@
 			> .header
 				padding 0 12px
 				text-align center
-				font-size 0.5em
+				font-size 10px
 
 				&, *
 					cursor: default
@@ -59,29 +62,21 @@
 	</style>
 	<script>
 		this.draw = () => {
-			const now = new Date();
-
-			yyyy = now.getFullYear()
-			mm = (\0 + (now.getMonth() + 1)).slice -2
-			dd = (\0 + now.getDate()).slice -2
-			yyyymmdd = "<span class='yyyymmdd'>#yyyy/#mm/#dd</span>"
-
-			hh = (\0 + now.getHours()).slice -2
-			mm = (\0 + now.getMinutes()).slice -2
-			hhmm = "<span class='hhmm'>#hh:#mm</span>"
-
-			if now.get-seconds! % 2 == 0
-				hhmm .= replace ':' '<span style=\'visibility:visible\'>:</span>'
-			else
-				hhmm .= replace ':' '<span style=\'visibility:hidden\'>:</span>'
-
-			this.refs.time.innerHTML = "#yyyymmdd<br>#hhmm"
+			this.now = new Date();
+			this.yyyy = now.getFullYear();
+			this.mm = ('0' + (now.getMonth() + 1)).slice(-2);
+			this.dd = ('0' + now.getDate()).slice(-2);
+			this.hh = ('0' + now.getHours()).slice(-2);
+			this.nn = ('0' + now.getMinutes()).slice(-2);
+		};
 
 		this.on('mount', () => {
-			@draw!
-			this.clock = setInterval @draw, 1000ms
+			this.draw();
+			this.clock = setInterval(this.draw, 1000);
+		});
 
 		this.on('unmount', () => {
-			clearInterval @clock
+			clearInterval(this.clock);
+		});
 	</script>
 </mk-ui-header-clock>
diff --git a/src/web/app/desktop/tags/ui-header-nav.tag b/src/web/app/desktop/tags/ui-header-nav.tag
index 93819963e..9be1edea8 100644
--- a/src/web/app/desktop/tags/ui-header-nav.tag
+++ b/src/web/app/desktop/tags/ui-header-nav.tag
@@ -1,113 +1,139 @@
 <mk-ui-header-nav>
 	<ul if={ SIGNIN }>
-		<li class="home { active: page == 'home' }"><a href={ CONFIG.url }><i class="fa fa-home"></i>
-				<p>ホーム</p></a></li>
-		<li class="messaging"><a onclick={ messaging }><i class="fa fa-comments"></i>
-				<p>メッセージ</p><i class="fa fa-circle" if={ hasUnreadMessagingMessages }></i></a></li>
-		<li class="info"><a href="https://twitter.com/misskey_xyz" target="_blank"><i class="fa fa-info"></i>
-				<p>お知らせ</p></a></li>
-		<li class="tv"><a href="https://misskey.tk" target="_blank"><i class="fa fa-television"></i>
-				<p>MisskeyTV™</p></a></li>
-		<style>
-			:scope
+		<li class="home { active: page == 'home' }">
+			<a href={ CONFIG.url }>
+				<i class="fa fa-home"></i>
+				<p>ホーム</p>
+			</a>
+		</li>
+		<li class="messaging">
+			<a onclick={ messaging }>
+				<i class="fa fa-comments"></i>
+				<p>メッセージ</p>
+				<i class="fa fa-circle" if={ hasUnreadMessagingMessages }></i>
+			</a>
+		</li>
+		<li class="info">
+			<a href="https://twitter.com/misskey_xyz" target="_blank">
+				<i class="fa fa-info"></i>
+				<p>お知らせ</p>
+			</a>
+		</li>
+		<li class="tv">
+			<a href="https://misskey.tk" target="_blank">
+				<i class="fa fa-television"></i>
+				<p>MisskeyTV™</p>
+			</a>
+		</li>
+	</ul>
+	<style>
+		:scope
+			display inline-block
+			margin 0
+			padding 0
+			line-height 3rem
+			vertical-align top
+
+			> ul
 				display inline-block
 				margin 0
 				padding 0
-				line-height 3rem
 				vertical-align top
+				line-height 3rem
+				list-style none
 
-				> ul
+				> li
 					display inline-block
-					margin 0
-					padding 0
 					vertical-align top
-					line-height 3rem
-					list-style none
-
-					> li
-						display inline-block
-						vertical-align top
-						height 48px
-						line-height 48px
-
-						&.active
-							> a
-								border-bottom solid 3px $theme-color
+					height 48px
+					line-height 48px
 
+					&.active
 						> a
-							display inline-block
-							z-index 1
-							height 100%
-							padding 0 24px
-							font-size 1em
-							font-variant small-caps
-							color #9eaba8
+							border-bottom solid 3px $theme-color
+
+					> a
+						display inline-block
+						z-index 1
+						height 100%
+						padding 0 24px
+						font-size 1em
+						font-variant small-caps
+						color #9eaba8
+						text-decoration none
+						transition none
+						cursor pointer
+
+						*
+							pointer-events none
+
+						&:hover
+							color darken(#9eaba8, 20%)
 							text-decoration none
-							transition none
-							cursor pointer
 
-							*
-								pointer-events none
+						> i:first-child
+							margin-right 8px
 
-							&:hover
-								color darken(#9eaba8, 20%)
-								text-decoration none
+						> i:last-child
+							margin-left 5px
+							vertical-align super
+							font-size 10px
+							color $theme-color
 
-							> i:first-child
-								margin-right 8px
+							@media (max-width 1100px)
+								margin-left -5px
 
-							> i:last-child
-								margin-left 5px
-								vertical-align super
-								font-size 10px
-								color $theme-color
+						> p
+							display inline
+							margin 0
 
-								@media (max-width 1100px)
-									margin-left -5px
+							@media (max-width 1100px)
+								display none
 
-							> p
-								display inline
-								margin 0
+						@media (max-width 700px)
+							padding 0 12px
 
-								@media (max-width 1100px)
-									display none
+	</style>
+	<script>
+		this.mixin('i');
+		this.mixin('api');
+		this.mixin('stream');
 
-							@media (max-width 700px)
-								padding 0 12px
+		this.page = this.opts.page;
 
-		</style>
-		<script>
-			this.mixin('i');
-			this.mixin('api');
-			this.mixin('stream');
+		this.on('mount', () => {
+			this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
+			this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage);
 
-			this.page = this.opts.page
+			// Fetch count of unread messaging messages
+			this.api('messaging/unread').then(res => {
+				if (res.count > 0) {
+					this.update({
+						hasUnreadMessagingMessages: true
+					});
+				}
+			});
+		});
 
-			this.on('mount', () => {
-				this.stream.on 'read_all_messaging_messages' this.on-read-all-messaging-messages
-				this.stream.on 'unread_messaging_message' this.on-unread-messaging-message
+		this.on('unmount', () => {
+			this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
+			this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage);
+		});
 
-				// Fetch count of unread messaging messages
-				this.api 'messaging/unread' 
-				}).then((count) => {
-					if count.count > 0
-						this.has-unread-messaging-messages = true
-						this.update();
+		this.onReadAllMessagingMessages = () => {
+			this.update({
+				hasUnreadMessagingMessages: false
+			});
+		};
 
-			this.on('unmount', () => {
-				this.stream.off 'read_all_messaging_messages' this.on-read-all-messaging-messages
-				this.stream.off 'unread_messaging_message' this.on-unread-messaging-message
+		this.onUnreadMessagingMessage = () => {
+			this.update({
+				hasUnreadMessagingMessages: true
+			});
+		};
 
-			this.on-read-all-messaging-messages = () => {
-				this.has-unread-messaging-messages = false
-				this.update();
-
-			this.on-unread-messaging-message = () => {
-				this.has-unread-messaging-messages = true
-				this.update();
-
-			this.messaging = () => {
-				riot.mount document.body.appendChild(document.createElement('mk-messaging-window'));
- 		</script>
-	</ul>
+		this.messaging = () => {
+			riot.mount(document.body.appendChild(document.createElement('mk-messaging-window')));
+		};
+	</script>
 </mk-ui-header-nav>
diff --git a/src/web/app/desktop/tags/ui-header-notifications.tag b/src/web/app/desktop/tags/ui-header-notifications.tag
index 31dc45d0d..05a9e6d77 100644
--- a/src/web/app/desktop/tags/ui-header-notifications.tag
+++ b/src/web/app/desktop/tags/ui-header-notifications.tag
@@ -75,40 +75,36 @@
 
 	</style>
 	<script>
-		this.is-open = false
+		const contains = require('../../common/scripts/contains');
+
+		this.isOpen = false;
 
 		this.toggle = () => {
-			if @is-open
-				@close();
-			else
-				@open!
+			this.isOpen ? this.close() : this.open();
+		};
 
 		this.open = () => {
-			this.is-open = true
-			this.update();
-			all = document.query-selector-all 'body *'
-			Array.prototype.forEach.call all, (el) =>
-				el.addEventListener 'mousedown' @mousedown
+			this.update({
+				isOpen: true
+			});
+			document.querySelectorAll('body *').forEach(el => {
+				el.addEventListener('mousedown', this.mousedown);
+			});
+		};
 
 		this.close = () => {
-			this.is-open = false
-			this.update();
-			all = document.query-selector-all 'body *'
-			Array.prototype.forEach.call all, (el) =>
-				el.removeEventListener 'mousedown' @mousedown
+			this.update({
+				isOpen: false
+			});
+			document.querySelectorAll('body *').forEach(el => {
+				el.removeEventListener('mousedown', this.mousedown);
+			});
+		};
 
-		this.mousedown = (e) => {
+		this.mousedown = e => {
 			e.preventDefault();
-			if (!contains this.root, e.target) and (this.root != e.target)
-				@close();
-			return false
-
-		function contains(parent, child)
-			node = child.parentNode
-			while node?
-				if node == parent
-					return true
-				node = node.parentNode
-			return false
+			if (!contains(this.root, e.target) && this.root != e.target) this.close();
+			return false;
+		};
 	</script>
 </mk-ui-header-notifications>
diff --git a/src/web/app/desktop/tags/ui-header-search.tag b/src/web/app/desktop/tags/ui-header-search.tag
index f7e2842c7..ff1a313ce 100644
--- a/src/web/app/desktop/tags/ui-header-search.tag
+++ b/src/web/app/desktop/tags/ui-header-search.tag
@@ -34,8 +34,9 @@
 	<script>
 		this.mixin('page');
 
-		this.onsubmit = (e) => {
+		this.onsubmit = e => {
 			e.preventDefault();
-			this.page '/search:' + this.refs.q.value
+			this.page('/search:' + this.refs.q.value);
+		};
 	</script>
 </mk-ui-header-search>
diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index bd9df8823..d2b3edb4d 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -192,328 +192,354 @@
 
 	</style>
 	<script>
-		this.min-height = 40px
-		this.min-width = 200px
+		const contains = require('../../common/scripts/contains');
 
-		this.is-modal = if this.opts.is-modal? then this.opts.is-modal else false
-		this.can-close = if this.opts.can-close? then this.opts.can-close else true
-		this.is-flexible = !this.opts.height?
-		this.can-resize = not @is-flexible
+		this.minHeight = 40;
+		this.minWidth = 200;
+
+		this.isModal = this.opts.isModal != null ? this.opts.isModal : false;
+		this.canClose = this.opts.canClose != null ? this.opts.canClose : true;
+		this.isFlexible = this.opts.height == null;
+		this.canResize = !this.isFlexible;
 
 		this.on('mount', () => {
-			this.refs.main.style.width = this.opts.width || '530px' 
-			this.refs.main.style.height = this.opts.height || 'auto' 
+			this.refs.main.style.width = this.opts.width || '530px';
+			this.refs.main.style.height = this.opts.height || 'auto';
 
-			this.refs.main.style.top = '15%' 
-			this.refs.main.style.left = (window.inner-width / 2) - (this.refs.main.offset-width / 2) + 'px' 
+			this.refs.main.style.top = '15%';
+			this.refs.main.style.left = (window.innerWidth / 2) - (this.refs.main.offsetWidth / 2) + 'px';
 
-			this.refs.header.addEventListener 'contextmenu' (e) =>
+			this.refs.header.addEventListener('contextmenu', e => {
 				e.preventDefault();
+			});
 
-			window.addEventListener 'resize' this.on-browser-resize
+			window.addEventListener('resize', this.onBrowserResize);
 
-			@open!
+			this.open();
+		});
 
 		this.on('unmount', () => {
-			window.removeEventListener 'resize' this.on-browser-resize
+			window.removeEventListener('resize', this.onBrowserResize);
+		});
 
-		this.on-browser-resize = () => {
-			position = this.refs.main.get-bounding-client-rect!
-			browser-width = window.inner-width
-			browser-height = window.inner-height
-			window-width = this.refs.main.offset-width
-			window-height = this.refs.main.offset-height
-
-			if position.left < 0
-				this.refs.main.style.left = 0
-
-			if position.top < 0
-				this.refs.main.style.top = 0
-
-			if position.left + window-width > browser-width
-				this.refs.main.style.left = browser-width - window-width + 'px' 
-
-			if position.top + window-height > browser-height
-				this.refs.main.style.top = browser-height - window-height + 'px' 
+		this.onBrowserResize = () => {
+			const position = this.refs.main.getBoundingClientRect();
+			const browserWidth = window.innerWidth;
+			const browserHeight = window.innerHeight;
+			const windowWidth = this.refs.main.offsetWidth;
+			const windowHeight = this.refs.main.offsetHeight;
+			if (position.left < 0) this.refs.main.style.left = 0;
+			if (position.top < 0) this.refs.main.style.top = 0;
+			if (position.left + windowWidth > browserWidth) this.refs.main.style.left = browserWidth - windowWidth + 'px';
+			if (position.top + windowHeight > browserHeight) this.refs.main.style.top = browserHeight - windowHeight + 'px';
+		};
 
 		this.open = () => {
 			this.trigger('opening');
 
-			@top!
+			this.top();
 
-			if @is-modal
-				this.refs.bg.style.pointer-events = 'auto' 
-				Velocity(this.refs.bg, 'finish' true
+			if (this.isModal) {
+				this.refs.bg.style.pointerEvents = 'auto';
+				Velocity(this.refs.bg, 'finish', true);
 				Velocity(this.refs.bg, {
 					opacity: 1
 				}, {
-					queue: false
-					duration: 100ms
-					easing: 'linear' 
-				}
-
-			this.refs.main.style.pointer-events = 'auto' 
-			Velocity(this.refs.main, 'finish' true
-			Velocity(this.refs.main, {scale: 1.1} 0ms
-			Velocity(this.refs.main, {
-				opacity: 1
-				scale: 1
-			}, {
-				queue: false
-				duration: 200ms
-				easing: 'ease-out' 
+					queue: false,
+					duration: 100,
+					easing: 'linear'
+				});
 			}
 
-			#this.refs.main.focus();
+			this.refs.main.style.pointerEvents = 'auto';
+			Velocity(this.refs.main, 'finish', true);
+			Velocity(this.refs.main, { scale: 1.1 }, 0);
+			Velocity(this.refs.main, {
+				opacity: 1,
+				scale: 1
+			}, {
+				queue: false,
+				duration: 200,
+				easing: 'ease-out'
+			});
 
-			setTimeout =>
+			//this.refs.main.focus();
+
+			setTimeout(() => {
 				this.trigger('opened');
-			, 300ms
+			}, 300);
+		};
 
 		this.close = () => {
 			this.trigger('closing');
 
-			if @is-modal
-				this.refs.bg.style.pointer-events = 'none' 
-				Velocity(this.refs.bg, 'finish' true
+			if (this.isModal) {
+				this.refs.bg.style.pointerEvents = 'none';
+				Velocity(this.refs.bg, 'finish', true);
 				Velocity(this.refs.bg, {
 					opacity: 0
 				}, {
-					queue: false
-					duration: 300ms
-					easing: 'linear' 
-				}
-
-			this.refs.main.style.pointer-events = 'none' 
-			Velocity(this.refs.main, 'finish' true
-			Velocity(this.refs.main, {
-				opacity: 0
-				scale: 0.8
-			}, {
-				queue: false
-				duration: 300ms
-				easing: [ 0.5, -0.5, 1, 0.5 ]
+					queue: false,
+					duration: 300,
+					easing: 'linear'
+				});
 			}
 
-			setTimeout =>
+			this.refs.main.style.pointerEvents = 'none';
+			Velocity(this.refs.main, 'finish', true);
+			Velocity(this.refs.main, {
+				opacity: 0,
+				scale: 0.8
+			}, {
+				queue: false,
+				duration: 300,
+				easing: [ 0.5, -0.5, 1, 0.5 ]
+			});
+
+			setTimeout(() => {
 				this.trigger('closed');
-			, 300ms
+			}, 300);
+		};
 
 		// 最前面へ移動します
 		this.top = () => {
-			z = 0
+			let z = 0;
 
-			ws = document.query-selector-all 'mk-window' 
-			ws.forEach (w) !=>
-				if w == this.root then return
-				m = w.query-selector ':scope > .main'
-				mz = Number(document.default-view.get-computed-style m, null .z-index)
-				if mz > z then z := mz
+			const ws = document.querySelectorAll('mk-window');
+			ws.forEach(w => {
+				if (w == this.root) return;
+				const m = w.querySelector(':scope > .main');
+				const mz = Number(document.defaultView.getComputedStyle(m, null).zIndex);
+				if (mz > z) z = mz;
+			});
 
-			if z > 0
-				this.refs.main.style.z-index = z + 1
-				if @is-modal then this.refs.bg.style.z-index = z + 1
+			if (z > 0) {
+				this.refs.main.style.zIndex = z + 1;
+				if (this.isModal) this.refs.bg.style.zIndex = z + 1;
+			}
+		};
 
-		this.repel-move = (e) => {
+		this.repelMove = e => {
 			e.stopPropagation();
-			return true
+			return true;
+		};
 
-		this.bg-click = () => {
-			if @can-close
-				@close();
+		this.bgClick = () => {
+			if (this.canClose) this.close();
+		};
 
-		this.on-body-mousedown = (e) => {
-			@top!
-			true
+		this.onBodyMousedown = () => {
+			this.top();
+		};
 
 		// ヘッダー掴み時
-		this.on-header-mousedown = (e) => {
+		this.onHeaderMousedown = e => {
 			e.preventDefault();
 
-			if not contains this.refs.main, document.active-element
-				this.refs.main.focus();
+			if (!contains(this.refs.main, document.activeElement)) this.refs.main.focus();
 
-			position = this.refs.main.get-bounding-client-rect!
+			const position = this.refs.main.getBoundingClientRect();
 
-			click-x = e.client-x
-			click-y = e.client-y
-			move-base-x = click-x - position.left
-			move-base-y = click-y - position.top
-			browser-width = window.inner-width
-			browser-height = window.inner-height
-			window-width = this.refs.main.offset-width
-			window-height = this.refs.main.offset-height
+			const clickX = e.clientX;
+			const clickY = e.clientY;
+			const moveBaseX = clickX - position.left;
+			const moveBaseY = clickY - position.top;
+			const browserWidth = window.innerWidth;
+			const browserHeight = window.innerHeight;
+			const windowWidth = this.refs.main.offsetWidth;
+			const windowHeight = this.refs.main.offsetHeight;
 
 			// 動かした時
-			drag-listen (me) =>
-				move-left = me.client-x - move-base-x
-				move-top = me.client-y - move-base-y
+			dragListen(me => {
+				let moveLeft = me.clientX - moveBaseX;
+				let moveTop = me.clientY - moveBaseY;
 
 				// 上はみ出し
-				if move-top < 0
-					move-top = 0
+				if (moveTop < 0) moveTop = 0;
 
 				// 左はみ出し
-				if move-left < 0
-					move-left = 0
+				if (moveLeft < 0) moveLeft = 0;
 
 				// 下はみ出し
-				if move-top + window-height > browser-height
-					move-top = browser-height - window-height
+				if (moveTop + windowHeight > browserHeight) moveTop = browserHeight - windowHeight;
 
 				// 右はみ出し
-				if move-left + window-width > browser-width
-					move-left = browser-width - window-width
+				if (moveLeft + windowWidth > browserWidth) moveLeft = browserWidth - windowWidth;
 
-				this.refs.main.style.left = move-left + 'px' 
-				this.refs.main.style.top = move-top + 'px' 
+				this.refs.main.style.left = moveLeft + 'px';
+				this.refs.main.style.top = moveTop + 'px';
+			});
+		};
 
 		// 上ハンドル掴み時
-		this.on-top-handle-mousedown = (e) => {
+		this.onTopHandleMousedown = e => {
 			e.preventDefault();
 
-			base = e.client-y
-			height = parse-int((get-computed-style this.refs.main, '').height, 10)
-			top = parse-int((get-computed-style this.refs.main, '').top, 10)
+			const base = e.clientY;
+			const height = parseInt(getComputedStyle(this.refs.main, '').height, 10);
+			const top = parseInt(getComputedStyle(this.refs.main, '').top, 10);
 
 			// 動かした時
-			drag-listen (me) =>
-				move = me.client-y - base
-				if top + move > 0
-					if height + -move > @min-height
-						@apply-transform-height height + -move
-						@apply-transform-top top + move
-					else // 最小の高さより小さくなろうとした時
-						@apply-transform-height @min-height
-						@apply-transform-top top + (height - @min-height)
-				else // 上のはみ出し時
-					@apply-transform-height top + height
-					@apply-transform-top 0
+			dragListen(me => {
+				const move = me.clientY - base;
+				if (top + move > 0) {
+					if (height + -move > this.minHeight) {
+						this.applyTransformHeight(height + -move);
+						this.applyTransformTop(top + move);
+					} else { // 最小の高さより小さくなろうとした時
+						this.applyTransformHeight(this.minHeight);
+						this.applyTransformTop(top + (height - this.minHeight));
+					}
+				} else { // 上のはみ出し時
+					this.applyTransformHeight(top + height);
+					this.applyTransformTop(0);
+				}
+			});
+		};
 
 		// 右ハンドル掴み時
-		this.on-right-handle-mousedown = (e) => {
+		this.onRightHandleMousedown = e => {
 			e.preventDefault();
 
-			base = e.client-x
-			width = parse-int((get-computed-style this.refs.main, '').width, 10)
-			left = parse-int((get-computed-style this.refs.main, '').left, 10)
-			browser-width = window.inner-width
+			const base = e.clientX;
+			const width = parseInt(getComputedStyle(this.refs.main, '').width, 10);
+			const left = parseInt(getComputedStyle(this.refs.main, '').left, 10);
+			const browserWidth = window.innerWidth;
 
 			// 動かした時
-			drag-listen (me) =>
-				move = me.client-x - base
-				if left + width + move < browser-width
-					if width + move > @min-width
-						@apply-transform-width width + move
-					else // 最小の幅より小さくなろうとした時
-						@apply-transform-width @min-width
-				else // 右のはみ出し時
-					@apply-transform-width browser-width - left
+			dragListen(me => {
+				const move = me.clientX - base;
+				if (left + width + move < browserWidth) {
+					if (width + move > this.minWidth) {
+						this.applyTransformWidth(width + move);
+					} else { // 最小の幅より小さくなろうとした時
+						this.applyTransformWidth(this.minWidth);
+					}
+				} else { // 右のはみ出し時
+					this.applyTransformWidth(browserWidth - left);
+				}
+			});
+		};
 
 		// 下ハンドル掴み時
-		this.on-bottom-handle-mousedown = (e) => {
+		this.onBottomHandleMousedown = e => {
 			e.preventDefault();
 
-			base = e.client-y
-			height = parse-int((get-computed-style this.refs.main, '').height, 10)
-			top = parse-int((get-computed-style this.refs.main, '').top, 10)
-			browser-height = window.inner-height
+			const base = e.clientY;
+			const height = parseInt(getComputedStyle(this.refs.main, '').height, 10);
+			const top = parseInt(getComputedStyle(this.refs.main, '').top, 10);
+			const browserHeight = window.innerHeight;
 
 			// 動かした時
-			drag-listen (me) =>
-				move = me.client-y - base
-				if top + height + move < browser-height
-					if height + move > @min-height
-						@apply-transform-height height + move
-					else // 最小の高さより小さくなろうとした時
-						@apply-transform-height @min-height
-				else // 下のはみ出し時
-					@apply-transform-height browser-height - top
+			dragListen(me => {
+				const move = me.clientY - base;
+				if (top + height + move < browserHeight) {
+					if (height + move > this.minHeight) {
+						return this.applyTransformHeight(height + move);
+					} else { // 最小の高さより小さくなろうとした時
+						return this.applyTransformHeight(this.minHeight);
+					}
+				} else { // 下のはみ出し時
+					return this.applyTransformHeight(browserHeight - top);
+				}
+			});
+		};
 
 		// 左ハンドル掴み時
-		this.on-left-handle-mousedown = (e) => {
+		this.onLeftHandleMousedown = e => {
 			e.preventDefault();
 
-			base = e.client-x
-			width = parse-int((get-computed-style this.refs.main, '').width, 10)
-			left = parse-int((get-computed-style this.refs.main, '').left, 10)
+			const base = e.clientX;
+			const width = parseInt(getComputedStyle(this.refs.main, '').width, 10);
+			const left = parseInt(getComputedStyle(this.refs.main, '').left, 10);
 
 			// 動かした時
-			drag-listen (me) =>
-				move = me.client-x - base
-				if left + move > 0
-					if width + -move > @min-width
-						@apply-transform-width width + -move
-						@apply-transform-left left + move
-					else // 最小の幅より小さくなろうとした時
-						@apply-transform-width @min-width
-						@apply-transform-left left + (width - @min-width)
-				else // 左のはみ出し時
-					@apply-transform-width left + width
-					@apply-transform-left 0
+			dragListen(me => {
+				const move = me.clientX - base;
+				if (left + move > 0) {
+					if (width + -move > this.minWidth) {
+						this.applyTransformWidth(width + -move);
+						return this.applyTransformLeft(left + move);
+					} else { // 最小の幅より小さくなろうとした時
+						this.applyTransformWidth(this.minWidth);
+						return this.applyTransformLeft(left + (width - this.minWidth));
+					}
+				} else { // 左のはみ出し時
+					this.applyTransformWidth(left + width);
+					return this.applyTransformLeft(0);
+				}
+			});
+		};
 
 		// 左上ハンドル掴み時
-		this.on-top-left-handle-mousedown = (e) => {
-			this.on-top-handle-mousedown e
-			this.on-left-handle-mousedown e
+		this.onTopLeftHandleMousedown = e => {
+			this.onTopHandleMousedown(e);
+			this.onLeftHandleMousedown(e);
+		};
 
 		// 右上ハンドル掴み時
-		this.on-top-right-handle-mousedown = (e) => {
-			this.on-top-handle-mousedown e
-			this.on-right-handle-mousedown e
+		this.onTopRightHandleMousedown = e => {
+			this.onTopHandleMousedown(e);
+			this.onRightHandleMousedown(e);
+		};
 
 		// 右下ハンドル掴み時
-		this.on-bottom-right-handle-mousedown = (e) => {
-			this.on-bottom-handle-mousedown e
-			this.on-right-handle-mousedown e
+		this.onBottomRightHandleMousedown = e => {
+			this.onBottomHandleMousedown(e);
+			this.onRightHandleMousedown(e);
+		};
 
 		// 左下ハンドル掴み時
-		this.on-bottom-left-handle-mousedown = (e) => {
-			this.on-bottom-handle-mousedown e
-			this.on-left-handle-mousedown e
+		this.onBottomLeftHandleMousedown = e => {
+			this.onBottomHandleMousedown(e);
+			this.onLeftHandleMousedown(e);
+		};
 
 		// 高さを適用
-		this.apply-transform-height = (height) => {
-			this.refs.main.style.height = height + 'px' 
+		this.applyTransformHeight = height => {
+			this.refs.main.style.height = height + 'px';
+		};
 
 		// 幅を適用
-		this.apply-transform-width = (width) => {
-			this.refs.main.style.width = width + 'px' 
+		this.applyTransformWidth = width => {
+			this.refs.main.style.width = width + 'px';
+		};
 
 		// Y座標を適用
-		this.apply-transform-top = (top) => {
-			this.refs.main.style.top = top + 'px' 
+		this.applyTransformTop = top => {
+			this.refs.main.style.top = top + 'px';
+		};
 
 		// X座標を適用
-		this.apply-transform-left = (left) => {
-			this.refs.main.style.left = left + 'px' 
+		this.applyTransformLeft = left => {
+			this.refs.main.style.left = left + 'px';
+		};
 
-		function drag-listen fn
-			window.addEventListener 'mousemove'  fn
-			window.addEventListener 'mouseleave' drag-clear.bind null fn
-			window.addEventListener 'mouseup'    drag-clear.bind null fn
+		function dragListen(fn) {
+			window.addEventListener('mousemove',  fn);
+			window.addEventListener('mouseleave', dragClear.bind(null, fn));
+			window.addEventListener('mouseup',    dragClear.bind(null, fn));
+		}
 
-		function drag-clear fn
-			window.removeEventListener 'mousemove'  fn
-			window.removeEventListener 'mouseleave' drag-clear
-			window.removeEventListener 'mouseup'    drag-clear
+		function dragClear(fn) {
+			window.removeEventListener('mousemove',  fn);
+			window.removeEventListener('mouseleave', dragClear);
+			window.removeEventListener('mouseup',    dragClear);
+		}
 
-		this.ondragover = (e) => {
-			e.dataTransfer.dropEffect = 'none' 
+		this.ondragover = e => {
+			e.dataTransfer.dropEffect = 'none';
+		};
 
-		this.onKeydown = (e) => {
-			if e.which == 27 // Esc
-				if @can-close
+		this.onKeydown = e => {
+			if (e.which == 27) { // Esc
+				if (this.canClose) {
 					e.preventDefault();
 					e.stopPropagation();
-					@close();
+					this.close();
+				}
+			}
+		};
 
-		function contains(parent, child)
-			node = child.parentNode
-			while node?
-				if node == parent
-					return true
-				node = node.parentNode
-			return false
 	</script>
 </mk-window>

From c5a26efda4ab0d2fce4b47250381c67151dee0fc Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 01:02:32 +0900
Subject: [PATCH 16/32] wip

---
 src/web/app/common/tags/uploader.tag          | 65 +++++++-------
 src/web/app/desktop/tags/drive/browser.tag    | 90 +++++++++----------
 src/web/app/desktop/tags/drive/file.tag       |  4 +-
 src/web/app/desktop/tags/drive/folder.tag     |  4 +-
 .../app/desktop/tags/following-setuper.tag    |  4 +-
 .../tags/home-widgets/photo-stream.tag        |  6 +-
 .../desktop/tags/home-widgets/timeline.tag    |  4 +-
 src/web/app/desktop/tags/images-viewer.tag    |  2 +-
 src/web/app/desktop/tags/post-form.tag        |  6 +-
 src/web/app/mobile/tags/drive.tag             | 46 +++++-----
 src/web/app/mobile/tags/post-form.tag         |  4 +-
 11 files changed, 118 insertions(+), 117 deletions(-)

diff --git a/src/web/app/common/tags/uploader.tag b/src/web/app/common/tags/uploader.tag
index f6e99892a..51520d9ab 100644
--- a/src/web/app/common/tags/uploader.tag
+++ b/src/web/app/common/tags/uploader.tag
@@ -142,54 +142,57 @@
 	<script>
 		this.mixin('i');
 
-		this.uploads = []
+		this.uploads = [];
 
-		
 		this.upload = (file, folder) => {
-			id = Math.random!
+			const id = Math.random();
 
-			ctx =
-				id: id
-				name: file.name || 'untitled' 
+			const ctx = {
+				id: id,
+				name: file.name || 'untitled',
 				progress: undefined
+			};
 
-			@uploads.push ctx
-			this.trigger 'change-uploads' @uploads
+			this.uploads.push(ctx);
+			this.trigger('change-uploads', this.uploads);
 			this.update();
 
-			reader = new FileReader!
-			reader.onload = (e) =>
-				ctx.img = e.target.result
+			const reader = new FileReader();
+			reader.onload = e => {
+				ctx.img = e.target.result;
 				this.update();
-			reader.read-as-data-URL file
+			};
+			reader.readAsDataURL(file);
 
-			data = new FormData!
-			data.append 'i' this.I.token
-			data.append 'file' file
+			const data = new FormData();
+			data.append('i', this.I.token);
+			data.append('file', file);
 
-			if folder?
-				data.append 'folder_id' folder
+			if (folder) data.append('folder_id', folder);
 
-			xhr = new XMLHttpRequest!
-			xhr.open 'POST' CONFIG.apiUrl + '/drive/files/create' true
-			xhr.onload = (e) =>
-				drive-file = JSON.parse e.target.response
+			const xhr = new XMLHttpRequest();
+			xhr.open('POST', CONFIG.apiUrl + '/drive/files/create', true);
+			xhr.onload = e => {
+				const driveFile = JSON.parse(e.target.response);
 
-				this.trigger 'uploaded' drive-file
+				this.trigger('uploaded', driveFile);
 
-				this.uploads = @uploads.filter (x) -> x.id != id
-				this.trigger 'change-uploads' @uploads
+				this.uploads = this.uploads.filter(x => x.id != id);
+				this.trigger('change-uploads', this.uploads);
 
 				this.update();
+			};
 
-			xhr.upload.onprogress = (e) =>
-				if e.length-computable
-					if ctx.progress == undefined
-						ctx.progress = {}
-					ctx.progress.max = e.total
-					ctx.progress.value = e.loaded
+			xhr.upload.onprogress = e => {
+				if (e.lengthComputable) {
+					if (ctx.progress == undefined) ctx.progress = {};
+					ctx.progress.max = e.total;
+					ctx.progress.value = e.loaded;
 					this.update();
+				}
+			};
 
-			xhr.send data
+			xhr.send(data);
+		};
 	</script>
 </mk-uploader>
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index 51c26943a..1c6ed53ca 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -238,6 +238,8 @@
 
 	</style>
 	<script>
+		const contains = require('../../../common/scripts/contains');
+
 		this.mixin('api');
 		this.mixin('dialog');
 		this.mixin('input-dialog');
@@ -253,67 +255,70 @@
 		// * null でルートを表す
 		this.folder = null;
 
-		this.multiple = if this.opts.multiple? then this.opts.multiple else false
+		this.multiple = this.opts.multiple != null ? this.opts.multiple : false;
 
 		// ドロップされようとしているか
 		this.draghover = false;
 
 		// 自信の所有するアイテムがドラッグをスタートさせたか
 		// (自分自身の階層にドロップできないようにするためのフラグ)
-		this.is-drag-source = false;
+		this.isDragSource = false;
 
 		this.on('mount', () => {
-			this.refs.uploader.on('uploaded', (file) => {
-				@add-file file, true
+			this.refs.uploader.on('uploaded', file => {
+				this.addFile(file, true);
+			});
 
-			this.refs.uploader.on('change-uploads', (uploads) => {
-				this.uploads = uploads
-				this.update();
+			this.refs.uploader.on('change-uploads', uploads => {
+				this.update({
+					uploads: uploads
+				});
+			});
 
-			this.stream.on 'drive_file_created' this.on-stream-drive-file-created
-			this.stream.on 'drive_file_updated' this.on-stream-drive-file-updated
-			this.stream.on 'drive_folder_created' this.on-stream-drive-folder-created
-			this.stream.on 'drive_folder_updated' this.on-stream-drive-folder-updated
+			this.stream.on 'drive_file_created' this.onStreamDriveFileCreated
+			this.stream.on 'drive_file_updated' this.onStreamDriveFileUpdated
+			this.stream.on 'drive_folder_created' this.onStreamDriveFolderCreated
+			this.stream.on 'drive_folder_updated' this.onStreamDriveFolderUpdated
 
 			// Riotのバグでnullを渡しても""になる
 			// https://github.com/riot/riot/issues/2080
 			#if this.opts.folder?
 			if this.opts.folder? and this.opts.folder != ''
-				@move this.opts.folder
+				this.move this.opts.folder
 			else
-				@load!
+				this.load();
 
 		this.on('unmount', () => {
-			this.stream.off 'drive_file_created' this.on-stream-drive-file-created
-			this.stream.off 'drive_file_updated' this.on-stream-drive-file-updated
-			this.stream.off 'drive_folder_created' this.on-stream-drive-folder-created
-			this.stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
+			this.stream.off 'drive_file_created' this.onStreamDriveFileCreated
+			this.stream.off 'drive_file_updated' this.onStreamDriveFileUpdated
+			this.stream.off 'drive_folder_created' this.onStreamDriveFolderCreated
+			this.stream.off 'drive_folder_updated' this.onStreamDriveFolderUpdated
 
-		this.on-stream-drive-file-created = (file) => {
-			@add-file file, true
+		this.onStreamDriveFileCreated = (file) => {
+			this.addFile file, true
 
-		this.on-stream-drive-file-updated = (file) => {
+		this.onStreamDriveFileUpdated = (file) => {
 			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				@remove-file file
 			else
-				@add-file file, true
+				this.addFile file, true
 
-		this.on-stream-drive-folder-created = (folder) => {
-			@add-folder folder, true
+		this.onStreamDriveFolderCreated = (folder) => {
+			this.addFolder folder, true
 
-		this.on-stream-drive-folder-updated = (folder) => {
+		this.onStreamDriveFolderUpdated = (folder) => {
 			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
-				@remove-folder folder
+				this.removeFolder folder
 			else
-				@add-folder folder, true
+				this.addFolder folder, true
 
 		this.onmousedown = (e) => {
 			if (contains this.refs.folders-container, e.target) or (contains this.refs.files-container, e.target)
 				return true
 
-			rect = this.refs.main.get-bounding-client-rect!
+			rect = this.refs.main.getBoundingClientRect();
 
 			left = e.pageX + this.refs.main.scroll-left - rect.left - window.pageXOffset
 			top = e.pageY + this.refs.main.scroll-top - rect.top - window.pageYOffset
@@ -341,13 +346,13 @@
 					this.refs.selection.style.top = cursorY + 'px' 
 
 			up = (e) =>
-				document.document-element.removeEventListener 'mousemove' move
-				document.document-element.removeEventListener 'mouseup' up
+				document.documentElement.removeEventListener 'mousemove' move
+				document.documentElement.removeEventListener 'mouseup' up
 
 				this.refs.selection.style.display = 'none' 
 
-			document.document-element.addEventListener 'mousemove' move
-			document.document-element.addEventListener 'mouseup' up
+			document.documentElement.addEventListener 'mousemove' move
+			document.documentElement.addEventListener 'mouseup' up
 
 		this.path-oncontextmenu = (e) => {
 			e.preventDefault();
@@ -359,7 +364,7 @@
 			e.stopPropagation();
 
 			// ドラッグ元が自分自身の所有するアイテムかどうか
-			if !@is-drag-source
+			if !@isDragSource
 				// ドラッグされてきたものがファイルだったら
 				if e.dataTransfer.effectAllowed == 'all' 
 					e.dataTransfer.dropEffect = 'copy' 
@@ -373,7 +378,7 @@
 
 		this.ondragenter = (e) => {
 			e.preventDefault();
-			if !@is-drag-source
+			if !@isDragSource
 				this.draghover = true
 
 		this.ondragleave = (e) => {
@@ -421,7 +426,7 @@
 					return false
 				if (this.folders.some (f) => f.id == folder)
 					return false
-				@remove-folder folder
+				this.removeFolder folder
 				this.api('drive/folders/update', {
 					folder_id: folder
 					parent_id: if this.folder? then this.folder.id else null
@@ -483,7 +488,7 @@
 				name: name
 				folder_id: if this.folder? then this.folder.id else undefined
 			}).then((folder) => {
-				@add-folder folder, true
+				this.addFolder folder, true
 				this.update();
 			.catch (err) =>
 				console.error err
@@ -533,7 +538,7 @@
 					x folder.parent
 
 				this.update();
-				@load!
+				this.load();
 			.catch (err, text-status) ->
 				console.error err
 
@@ -590,7 +595,7 @@
 				this.folder = null
 				this.hierarchyFolders = []
 				this.update();
-				@load!
+				this.load();
 
 		this.load = () => {
 			this.folders = []
@@ -636,20 +641,13 @@
 			complete = =>
 				if flag
 					load-folders.forEach (folder) =>
-						@add-folder folder
+						this.addFolder folder
 					load-files.forEach (file) =>
-						@add-file file
+						this.addFile file
 					this.loading = false
 					this.update();
 				else
 					flag := true
 
-		function contains(parent, child)
-			node = child.parentNode
-			while node?
-				if node == parent
-					return true
-				node = node.parentNode
-			return false
 	</script>
 </mk-drive-browser>
diff --git a/src/web/app/desktop/tags/drive/file.tag b/src/web/app/desktop/tags/drive/file.tag
index 58c6b40a4..e35d204b6 100644
--- a/src/web/app/desktop/tags/drive/file.tag
+++ b/src/web/app/desktop/tags/drive/file.tag
@@ -200,10 +200,10 @@
 
 			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
 			// (=あなたの子供が、ドラッグを開始しましたよ)
-			this.browser.is-drag-source = true
+			this.browser.isDragSource = true
 
 		this.ondragend = (e) => {
 			this.is-dragging = false
-			this.browser.is-drag-source = false
+			this.browser.isDragSource = false
 	</script>
 </mk-drive-browser-file>
diff --git a/src/web/app/desktop/tags/drive/folder.tag b/src/web/app/desktop/tags/drive/folder.tag
index c9bc5d7f0..abc9368f4 100644
--- a/src/web/app/desktop/tags/drive/folder.tag
+++ b/src/web/app/desktop/tags/drive/folder.tag
@@ -155,11 +155,11 @@
 
 			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
 			// (=あなたの子供が、ドラッグを開始しましたよ)
-			this.browser.is-drag-source = true
+			this.browser.isDragSource = true
 
 		this.ondragend = (e) => {
 			this.is-dragging = false
-			this.browser.is-drag-source = false
+			this.browser.isDragSource = false
 
 		this.oncontextmenu = (e) => {
 			e.preventDefault();
diff --git a/src/web/app/desktop/tags/following-setuper.tag b/src/web/app/desktop/tags/following-setuper.tag
index 6381e4d8d..03b26b10e 100644
--- a/src/web/app/desktop/tags/following-setuper.tag
+++ b/src/web/app/desktop/tags/following-setuper.tag
@@ -133,7 +133,7 @@
 		this.page = 0
 
 		this.on('mount', () => {
-			@load!
+			this.load();
 
 		this.load = () => {
 			this.loading = true
@@ -155,7 +155,7 @@
 				this.page = 0
 			else
 				this.page++
-			@load!
+			this.load();
 
 		this.close = () => {
 			this.unmount();
diff --git a/src/web/app/desktop/tags/home-widgets/photo-stream.tag b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
index 042e3ea20..3ebbf6a1e 100644
--- a/src/web/app/desktop/tags/home-widgets/photo-stream.tag
+++ b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
@@ -64,7 +64,7 @@
 		this.initializing = true
 
 		this.on('mount', () => {
-			this.stream.on 'drive_file_created' this.on-stream-drive-file-created
+			this.stream.on 'drive_file_created' this.onStreamDriveFileCreated
 
 			this.api('drive/stream', {
 				type: 'image/*'
@@ -75,9 +75,9 @@
 				this.update();
 
 		this.on('unmount', () => {
-			this.stream.off 'drive_file_created' this.on-stream-drive-file-created
+			this.stream.off 'drive_file_created' this.onStreamDriveFileCreated
 
-		this.on-stream-drive-file-created = (file) => {
+		this.onStreamDriveFileCreated = (file) => {
 			if /^image\/.+$/.test file.type
 				@images.unshift file
 				if @images.length > 9
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index 30acc75ac..69417aa83 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -98,10 +98,10 @@
 			this.refs.timeline.add-post post
 
 		this.on-stream-follow = () => {
-			@load!
+			this.load();
 
 		this.on-stream-unfollow = () => {
-			@load!
+			this.load();
 
 		this.on-scroll = () => {
 			current = window.scrollY + window.inner-height
diff --git a/src/web/app/desktop/tags/images-viewer.tag b/src/web/app/desktop/tags/images-viewer.tag
index 8d10ec656..e1ceeb0f5 100644
--- a/src/web/app/desktop/tags/images-viewer.tag
+++ b/src/web/app/desktop/tags/images-viewer.tag
@@ -30,7 +30,7 @@
 		this.image = @images.0
 
 		this.mousemove = (e) => {
-			rect = this.refs.view.get-bounding-client-rect!
+			rect = this.refs.view.getBoundingClientRect();
 			mouse-x = e.client-x - rect.left
 			mouse-y = e.client-y - rect.top
 			xp = mouse-x / this.refs.view.offset-width * 100
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index cb1693420..737c77dbf 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -324,7 +324,7 @@
 
 		this.on('mount', () => {
 			this.refs.uploader.on('uploaded', (file) => {
-				@add-file file
+				this.addFile file
 
 			this.refs.uploader.on('change-uploads', (uploads) => {
 				this.trigger 'change-uploading-files' uploads
@@ -382,7 +382,7 @@
 
 				// (ドライブの)ファイルだったら
 				if obj.type == 'file' 
-					@add-file obj.file
+					this.addFile obj.file
 			catch
 				// ignore
 
@@ -409,7 +409,7 @@
  			i = riot.mount browser, do
 				multiple: true
 			i[0].one 'selected' (files) =>
-				files.forEach @add-file
+				files.forEach this.addFile
 
 		this.change-file = () => {
 			files = this.refs.file.files
diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag
index 8d4383f6e..36c037d1a 100644
--- a/src/web/app/mobile/tags/drive.tag
+++ b/src/web/app/mobile/tags/drive.tag
@@ -146,10 +146,10 @@
 		this.multiple = if this.opts.multiple? then this.opts.multiple else false
 
 		this.on('mount', () => {
-			this.stream.on 'drive_file_created' this.on-stream-drive-file-created
-			this.stream.on 'drive_file_updated' this.on-stream-drive-file-updated
-			this.stream.on 'drive_folder_created' this.on-stream-drive-folder-created
-			this.stream.on 'drive_folder_updated' this.on-stream-drive-folder-updated
+			this.stream.on 'drive_file_created' this.onStreamDriveFileCreated
+			this.stream.on 'drive_file_updated' this.onStreamDriveFileUpdated
+			this.stream.on 'drive_folder_created' this.onStreamDriveFolderCreated
+			this.stream.on 'drive_folder_updated' this.onStreamDriveFolderUpdated
 
 			// Riotのバグでnullを渡しても""になる
 			// https://github.com/riot/riot/issues/2080
@@ -159,36 +159,36 @@
 			else if this.opts.file? and this.opts.file != ''
 				@cf this.opts.file, true
 			else
-				@load!
+				this.load();
 
 		this.on('unmount', () => {
-			this.stream.off 'drive_file_created' this.on-stream-drive-file-created
-			this.stream.off 'drive_file_updated' this.on-stream-drive-file-updated
-			this.stream.off 'drive_folder_created' this.on-stream-drive-folder-created
-			this.stream.off 'drive_folder_updated' this.on-stream-drive-folder-updated
+			this.stream.off 'drive_file_created' this.onStreamDriveFileCreated
+			this.stream.off 'drive_file_updated' this.onStreamDriveFileUpdated
+			this.stream.off 'drive_folder_created' this.onStreamDriveFolderCreated
+			this.stream.off 'drive_folder_updated' this.onStreamDriveFolderUpdated
 
-		this.on-stream-drive-file-created = (file) => {
-			@add-file file, true
+		this.onStreamDriveFileCreated = (file) => {
+			this.addFile file, true
 
-		this.on-stream-drive-file-updated = (file) => {
+		this.onStreamDriveFileUpdated = (file) => {
 			current = if this.folder? then this.folder.id else null
 			if current != file.folder_id
 				@remove-file file
 			else
-				@add-file file, true
+				this.addFile file, true
 
-		this.on-stream-drive-folder-created = (folder) => {
-			@add-folder folder, true
+		this.onStreamDriveFolderCreated = (folder) => {
+			this.addFolder folder, true
 
-		this.on-stream-drive-folder-updated = (folder) => {
+		this.onStreamDriveFolderUpdated = (folder) => {
 			current = if this.folder? then this.folder.id else null
 			if current != folder.parent_id
-				@remove-folder folder
+				this.removeFolder folder
 			else
-				@add-folder folder, true
+				this.addFolder folder, true
 
 		@_move = (ev) =>
-			@move ev.item.folder
+			this.move ev.item.folder
 
 		this.move = (target-folder) => {
 			@cd target-folder
@@ -222,7 +222,7 @@
 
 				this.update();
 				this.trigger 'open-folder' this.folder, silent
-				@load!
+				this.load();
 			.catch (err, text-status) ->
 				console.error err
 
@@ -278,7 +278,7 @@
 				this.hierarchyFolders = []
 				this.update();
 				this.trigger('move-root');
-				@load!
+				this.load();
 
 		this.load = () => {
 			this.folders = []
@@ -326,9 +326,9 @@
 			complete = =>
 				if flag
 					load-folders.forEach (folder) =>
-						@add-folder folder
+						this.addFolder folder
 					load-files.forEach (file) =>
-						@add-file file
+						this.addFile file
 					this.loading = false
 					this.update();
 
diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag
index 43643f88c..27c6c005c 100644
--- a/src/web/app/mobile/tags/post-form.tag
+++ b/src/web/app/mobile/tags/post-form.tag
@@ -193,7 +193,7 @@
 
 		this.on('mount', () => {
 			this.refs.uploader.on('uploaded', (file) => {
-				@add-file file
+				this.addFile file
 
 			this.refs.uploader.on('change-uploads', (uploads) => {
 				this.trigger 'change-uploading-files' uploads
@@ -225,7 +225,7 @@
 				multiple: true
 			.0
 			browser.on('selected', (files) => {
-				files.forEach @add-file
+				files.forEach this.addFile
 
 		this.change-file = () => {
 			files = this.refs.file.files

From 2f840733d706695288acca10082f9f4a2e0c35d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?syuilo=E2=AD=90=EF=B8=8F?= <Syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 01:13:24 +0900
Subject: [PATCH 17/32] Update window.tag

---
 src/web/app/desktop/tags/window.tag | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/web/app/desktop/tags/window.tag b/src/web/app/desktop/tags/window.tag
index d2b3edb4d..3e7da9076 100644
--- a/src/web/app/desktop/tags/window.tag
+++ b/src/web/app/desktop/tags/window.tag
@@ -435,12 +435,12 @@
 				const move = me.clientY - base;
 				if (top + height + move < browserHeight) {
 					if (height + move > this.minHeight) {
-						return this.applyTransformHeight(height + move);
+						this.applyTransformHeight(height + move);
 					} else { // 最小の高さより小さくなろうとした時
-						return this.applyTransformHeight(this.minHeight);
+						this.applyTransformHeight(this.minHeight);
 					}
 				} else { // 下のはみ出し時
-					return this.applyTransformHeight(browserHeight - top);
+					this.applyTransformHeight(browserHeight - top);
 				}
 			});
 		};
@@ -459,14 +459,14 @@
 				if (left + move > 0) {
 					if (width + -move > this.minWidth) {
 						this.applyTransformWidth(width + -move);
-						return this.applyTransformLeft(left + move);
+						this.applyTransformLeft(left + move);
 					} else { // 最小の幅より小さくなろうとした時
 						this.applyTransformWidth(this.minWidth);
-						return this.applyTransformLeft(left + (width - this.minWidth));
+						this.applyTransformLeft(left + (width - this.minWidth));
 					}
 				} else { // 左のはみ出し時
 					this.applyTransformWidth(left + width);
-					return this.applyTransformLeft(0);
+					this.applyTransformLeft(0);
 				}
 			});
 		};

From b66bac7851c331c8281418f9aa5a6068edc552d7 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 09:49:35 +0900
Subject: [PATCH 18/32] wip

---
 src/web/app/boot.js                        |   5 +-
 src/web/app/desktop/tags/drive/browser.tag | 565 +++++++++++----------
 2 files changed, 298 insertions(+), 272 deletions(-)

diff --git a/src/web/app/boot.js b/src/web/app/boot.js
index ab147eb56..06e457e2b 100644
--- a/src/web/app/boot.js
+++ b/src/web/app/boot.js
@@ -27,13 +27,16 @@ riot.mixin({
 // ↓ iOS待ちPolyfill (SEE: http://caniuse.com/#feat=fetch)
 require('whatwg-fetch');
 
-// ↓ NodeList、HTMLCollectionで forEach を使えるようにする
+// ↓ NodeList、HTMLCollection、FileListで forEach を使えるようにする
 if (NodeList.prototype.forEach === undefined) {
 	NodeList.prototype.forEach = Array.prototype.forEach;
 }
 if (HTMLCollection.prototype.forEach === undefined) {
 	HTMLCollection.prototype.forEach = Array.prototype.forEach;
 }
+if (FileList.prototype.forEach === undefined) {
+	FileList.prototype.forEach = Array.prototype.forEach;
+}
 
 // ↓ iOSでプライベートモードだとlocalStorageが使えないので既存のメソッドを上書きする
 try {
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index 1c6ed53ca..989ec48ae 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -8,7 +8,7 @@
 		</div>
 		<input class="search" type="search" placeholder="&#xf002; 検索"/>
 	</nav>
-	<div class="main { uploading: uploads.length > 0, loading: loading }" ref="main" onmousedown={ onmousedown } ondragover={ ondragover } ondragenter={ ondragenter } ondragleave={ ondragleave } ondrop={ ondrop } oncontextmenu={ oncontextmenu }>
+	<div class="main { uploading: uploads.length > 0, fetching: fetching }" ref="main" onmousedown={ onmousedown } ondragover={ ondragover } ondragenter={ ondragenter } ondragleave={ ondragleave } ondrop={ ondrop } oncontextmenu={ oncontextmenu }>
 		<div class="selection" ref="selection"></div>
 		<div class="contents" ref="contents">
 			<div class="folders" ref="foldersContainer" if={ folders.length > 0 }>
@@ -23,13 +23,13 @@
 				</virtual>
 				<button if={ moreFiles }>もっと読み込む</button>
 			</div>
-			<div class="empty" if={ files.length == 0 && folders.length == 0 && !loading }>
+			<div class="empty" if={ files.length == 0 && folders.length == 0 && !fetching }>
 				<p if={ draghover }>ドロップですか?いいですよ、ボクはカワイイですからね</p>
 				<p if={ !draghover && folder == null }><strong>ドライブには何もありません。</strong><br/>右クリックして「ファイルをアップロード」を選んだり、ファイルをドラッグ&ドロップすることでもアップロードできます。</p>
 				<p if={ !draghover && folder != null }>このフォルダーは空です</p>
 			</div>
 		</div>
-		<div class="loading" if={ loading }>
+		<div class="loading" if={ fetching }>
 			<div class="spinner">
 				<div class="dot1"></div>
 				<div class="dot2"></div>
@@ -133,7 +133,7 @@
 				&, *
 					user-select none
 
-				&.loading
+				&.fetching
 					cursor wait !important
 
 					*
@@ -184,7 +184,7 @@
 						> p
 							margin 0
 
-				> .loading
+				> .fetching
 					.spinner
 						margin 100px auto
 						width 40px
@@ -275,379 +275,402 @@
 				});
 			});
 
-			this.stream.on 'drive_file_created' this.onStreamDriveFileCreated
-			this.stream.on 'drive_file_updated' this.onStreamDriveFileUpdated
-			this.stream.on 'drive_folder_created' this.onStreamDriveFolderCreated
-			this.stream.on 'drive_folder_updated' this.onStreamDriveFolderUpdated
+			this.stream.on('drive_file_created', this.onStreamDriveFileCreated);
+			this.stream.on('drive_file_updated', this.onStreamDriveFileUpdated);
+			this.stream.on('drive_folder_created', this.onStreamDriveFolderCreated);
+			this.stream.on('drive_folder_updated', this.onStreamDriveFolderUpdated);
 
 			// Riotのバグでnullを渡しても""になる
 			// https://github.com/riot/riot/issues/2080
-			#if this.opts.folder?
-			if this.opts.folder? and this.opts.folder != ''
-				this.move this.opts.folder
-			else
+			//if (this.opts.folder)
+			if (this.opts.folder && this.opts.folder != '') {
+				this.move(this.opts.folder);
+			} else {
 				this.load();
+			}
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'drive_file_created' this.onStreamDriveFileCreated
-			this.stream.off 'drive_file_updated' this.onStreamDriveFileUpdated
-			this.stream.off 'drive_folder_created' this.onStreamDriveFolderCreated
-			this.stream.off 'drive_folder_updated' this.onStreamDriveFolderUpdated
+			this.stream.off('drive_file_created', this.onStreamDriveFileCreated);
+			this.stream.off('drive_file_updated', this.onStreamDriveFileUpdated);
+			this.stream.off('drive_folder_created', this.onStreamDriveFolderCreated);
+			this.stream.off('drive_folder_updated', this.onStreamDriveFolderUpdated);
+		});
 
-		this.onStreamDriveFileCreated = (file) => {
-			this.addFile file, true
+		this.onStreamDriveFileCreated = file => {
+			this.addFile(file, true);
+		};
 
-		this.onStreamDriveFileUpdated = (file) => {
-			current = if this.folder? then this.folder.id else null
-			if current != file.folder_id
-				@remove-file file
-			else
-				this.addFile file, true
+		this.onStreamDriveFileUpdated = file => {
+			const current = this.folder ? this.folder.id : null;
+			if (current != file.folder_id) {
+				this.removeFile(file);
+			} else {
+				this.addFile(file, true);
+			}
+		};
 
-		this.onStreamDriveFolderCreated = (folder) => {
-			this.addFolder folder, true
+		this.onStreamDriveFolderCreated = folder => {
+			this.addFolder(folder, true);
+		};
 
-		this.onStreamDriveFolderUpdated = (folder) => {
-			current = if this.folder? then this.folder.id else null
-			if current != folder.parent_id
-				this.removeFolder folder
-			else
-				this.addFolder folder, true
+		this.onStreamDriveFolderUpdated = folder => {
+			const current = this.folder ? this.folder.id : null;
+			if (current != folder.parent_id) {
+				this.removeFolder(folder);
+			} else {
+				this.addFolder(folder, true);
+			}
+		};
 
-		this.onmousedown = (e) => {
-			if (contains this.refs.folders-container, e.target) or (contains this.refs.files-container, e.target)
-				return true
+		this.onmousedown = e => {
+			if (contains(this.refs.foldersContainer, e.target) || contains(this.refs.filesContainer, e.target)) return true;
 
-			rect = this.refs.main.getBoundingClientRect();
+			const rect = this.refs.main.getBoundingClientRect();
 
-			left = e.pageX + this.refs.main.scroll-left - rect.left - window.pageXOffset
-			top = e.pageY + this.refs.main.scroll-top - rect.top - window.pageYOffset
+			const left = e.pageX + this.refs.main.scrollLeft - rect.left - window.pageXOffset
+			const top = e.pageY + this.refs.main.scrollTop - rect.top - window.pageYOffset
 
-			move = (e) =>
-				this.refs.selection.style.display = 'block' 
+			const move = e => {
+				this.refs.selection.style.display = 'block';
 
-				cursorX = e.pageX + this.refs.main.scroll-left - rect.left - window.pageXOffset
-				cursorY = e.pageY + this.refs.main.scroll-top - rect.top - window.pageYOffset
-				w = cursorX - left
-				h = cursorY - top
+				const cursorX = e.pageX + this.refs.main.scrollLeft - rect.left - window.pageXOffset;
+				const cursorY = e.pageY + this.refs.main.scrollTop - rect.top - window.pageYOffset;
+				const w = cursorX - left;
+				const h = cursorY - top;
 
-				if w > 0
-					this.refs.selection.style.width = w + 'px' 
-					this.refs.selection.style.left = left + 'px' 
-				else
-					this.refs.selection.style.width = -w + 'px' 
-					this.refs.selection.style.left = cursorX + 'px' 
+				if (w > 0) {
+					this.refs.selection.style.width = w + 'px';
+					this.refs.selection.style.left = left + 'px';
+				} else {
+					this.refs.selection.style.width = -w + 'px';
+					this.refs.selection.style.left = cursorX + 'px';
+				}
 
-				if h > 0
-					this.refs.selection.style.height = h + 'px' 
-					this.refs.selection.style.top = top + 'px' 
-				else
-					this.refs.selection.style.height = -h + 'px' 
-					this.refs.selection.style.top = cursorY + 'px' 
+				if (h > 0) {
+					this.refs.selection.style.height = h + 'px';
+					this.refs.selection.style.top = top + 'px';
+				} else {
+					this.refs.selection.style.height = -h + 'px';
+					this.refs.selection.style.top = cursorY + 'px';
+				}
+			};
 
-			up = (e) =>
-				document.documentElement.removeEventListener 'mousemove' move
-				document.documentElement.removeEventListener 'mouseup' up
+			up = e => {
+				document.documentElement.removeEventListener('mousemove', move);
+				document.documentElement.removeEventListener('mouseup', up);
 
-				this.refs.selection.style.display = 'none' 
+				this.refs.selection.style.display = 'none';
+			};
 
-			document.documentElement.addEventListener 'mousemove' move
-			document.documentElement.addEventListener 'mouseup' up
+			document.documentElement.addEventListener('mousemove', move);
+			document.documentElement.addEventListener('mouseup', up);
+		};
 
-		this.path-oncontextmenu = (e) => {
+		this.pathOncontextmenu = e => {
 			e.preventDefault();
 			e.stopImmediatePropagation();
-			return false
+			return false;
+		};
 
-		this.ondragover = (e) => {
+		this.ondragover = e => {
 			e.preventDefault();
 			e.stopPropagation();
 
 			// ドラッグ元が自分自身の所有するアイテムかどうか
-			if !@isDragSource
+			if (!this.isDragSource) {
 				// ドラッグされてきたものがファイルだったら
-				if e.dataTransfer.effectAllowed == 'all' 
-					e.dataTransfer.dropEffect = 'copy' 
-				else
-					e.dataTransfer.dropEffect = 'move' 
-				this.draghover = true
-			else
+				e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
+				this.draghover = true;
+			} else {
 				// 自分自身にはドロップさせない
-				e.dataTransfer.dropEffect = 'none' 
-			return false
+				e.dataTransfer.dropEffect = 'none';
+				return false;
+			}
+		};
 
-		this.ondragenter = (e) => {
+		this.ondragenter = e => {
 			e.preventDefault();
-			if !@isDragSource
-				this.draghover = true
+			if (!this.isDragSource) this.draghover = true;
+		};
 
-		this.ondragleave = (e) => {
-			this.draghover = false
+		this.ondragleave = e => {
+			this.draghover = false;
+		};
 
-		this.ondrop = (e) => {
+		this.ondrop = e => {
 			e.preventDefault();
 			e.stopPropagation();
 
-			this.draghover = false
+			this.draghover = false;
 
 			// ドロップされてきたものがファイルだったら
-			if e.dataTransfer.files.length > 0
-				Array.prototype.forEach.call e.dataTransfer.files, (file) =>
-					@upload file, this.folder
-				return false
+			if (e.dataTransfer.files.length > 0) {
+				e.dataTransfer.files.forEach(file => {
+					this.upload(file, this.folder);
+				});
+				return false;
+			}
 
 			// データ取得
-			data = e.dataTransfer.get-data 'text'
-			if !data?
-				return false
+			const data = e.dataTransfer.getData('text');
+			if (data == null) return false;
 
 			// パース
-			obj = JSON.parse data
+			// TODO: JSONじゃなかったら中断
+			const obj = JSON.parse(data);
 
 			// (ドライブの)ファイルだったら
-			if obj.type == 'file' 
-				file = obj.id
-				if (this.files.some (f) => f.id == file)
-					return false
-				@remove-file file
+			if (obj.type == 'file') {
+				const file = obj.id;
+				if (this.files.some(f => f.id == file)) return false;
+				this.removeFile(file);
 				this.api('drive/files/update', {
-					file_id: file
-					folder_id: if this.folder? then this.folder.id else null
-				}).then(() => {
-					// something
-				.catch (err, text-status) =>
-					console.error err
-
+					file_id: file,
+					folder_id: this.folder ? this.folder.id : null
+				});
 			// (ドライブの)フォルダーだったら
-			else if obj.type == 'folder' 
-				folder = obj.id
+			} else if (obj.type == 'folder') {
+				const folder = obj.id;
 				// 移動先が自分自身ならreject
-				if this.folder? and folder == this.folder.id
-					return false
-				if (this.folders.some (f) => f.id == folder)
-					return false
-				this.removeFolder folder
+				if (this.folder && folder == this.folder.id) return false;
+				if (this.folders.some(f => f.id == folder)) return false;
+				this.removeFolder(folder);
 				this.api('drive/folders/update', {
-					folder_id: folder
-					parent_id: if this.folder? then this.folder.id else null
+					folder_id: folder,
+					parent_id: this.folder ? this.folder.id : null
 				}).then(() => {
 					// something
-				.catch (err) =>
-					if err == 'detected-circular-definition'
-						@dialog do
-							'<i class="fa fa-exclamation-triangle"></i>操作を完了できません'
-							'移動先のフォルダーは、移動するフォルダーのサブフォルダーです。'
-							[
-								text: 'OK' 
-							]
+				}).catch(err => {
+					switch (err) {
+						case 'detected-circular-definition':
+							this.dialog('<i class="fa fa-exclamation-triangle"></i>操作を完了できません',
+								'移動先のフォルダーは、移動するフォルダーのサブフォルダーです。', [{
+								text: 'OK'
+							}]);
+							break;
+						default:
+							alert('不明なエラー' + err);
+					}
+				});
+			}
 
-			return false
+			return false;
+		};
 
-		this.oncontextmenu = (e) => {
+		this.oncontextmenu = e => {
 			e.preventDefault();
 			e.stopImmediatePropagation();
 
-			ctx = document.body.appendChild(document.createElement('mk-drive-browser-base-contextmenu'));
- 			ctx = riot.mount ctx, do
+			const ctx = riot.mount(document.body.appendChild(document.createElement('mk-drive-browser-base-contextmenu')), {
 				browser: this
-			ctx = ctx.0
-			ctx.open do
-				x: e.pageX - window.pageXOffset
+			})[0];
+			ctx.open({
+				x: e.pageX - window.pageXOffset,
 				y: e.pageY - window.pageYOffset
+			});
 
-			return false
+			return false;
+		};
 
-		this.select-local-file = () => {
-			this.refs.file-input.click();
+		this.selectLocalFile = () => {
+			this.refs.fileInput.click();
+		};
 
-		this.url-upload = () => {
-			url <~ @input-dialog do
-				'URLアップロード'
-				'アップロードしたいファイルのURL'
-				null
-
-			if url? and url != ''
+		this.urlUpload = () => {
+			this.inputDialog('URLアップロード', 'アップロードしたいファイルのURL', null, url => {
 				this.api('drive/files/upload_from_url', {
-					url: url
-					folder_id: if this.folder? then this.folder.id else undefined
+					url: url,
+					folder_id: this.folder ? this.folder.id : undefined
+				});
 
-				@dialog do
-					'<i class="fa fa-check"></i>アップロードをリクエストしました'
-					'アップロードが完了するまで時間がかかる場合があります。'
-					[
-						text: 'OK' 
-					]
+				this.dialog('<i class="fa fa-check"></i>アップロードをリクエストしました',
+					'アップロードが完了するまで時間がかかる場合があります。', [{
+					text: 'OK'
+				}]);
+			});
+		};
 
 		this.createFolder = () => {
-			name <~ @input-dialog do
-				'フォルダー作成'
-				'フォルダー名'
-				null
+			this.inputDialog('フォルダー作成', 'フォルダー名', null, name => {
+				this.api('drive/folders/create', {
+					name: name,
+					folder_id: this.folder ? this.folder.id : undefined
+				}).then(folder => {
+					this.addFolder(folder, true);
+					this.update();
+				});
+			});
+		};
 
-			this.api('drive/folders/create', {
-				name: name
-				folder_id: if this.folder? then this.folder.id else undefined
-			}).then((folder) => {
-				this.addFolder folder, true
-				this.update();
-			.catch (err) =>
-				console.error err
-
-		this.change-file-input = () => {
-			files = this.refs.file-input.files
-			for i from 0 to files.length - 1
-				file = files.item i
-				@upload file, this.folder
+		this.changeFileInput = () => {
+			this.refs.fileInput.files.forEach(file => {
+				this.upload(file, this.folder);
+			});
+		};
 
 		this.upload = (file, folder) => {
-			if folder? and typeof folder == 'object' 
-				folder = folder.id
-			this.refs.uploader.upload file, folder
+			if (folder && typeof folder == 'object') folder = folder.id;
+			this.refs.uploader.upload(file, folder);
+		};
 
-		this.get-selection = () => {
-			this.files.filter (file) -> file._selected
+		this.getSelection = () => {
+			this.files.filter(file => file._selected);
+		};
 
-		this.newWindow = (folder-id) => {
-			browser = document.body.appendChild(document.createElement('mk-drive-browser-window'));
- 			riot.mount browser, do
-				folder: folder-id
+		this.newWindow = folderId => {
+			riot.mount(document.body.appendChild(document.createElement('mk-drive-browser-window')), {
+				folder: folderId
+			});
+		};
 
-		this.move = (target-folder) => {
-			if target-folder? and typeof target-folder == 'object' 
-				target-folder = target-folder.id
+		this.move = target => {
+			if (target == null) {
+				this.goRoot();
+				return;
+			} else if (typeof target == 'object') {
+				target = target.id;
+			}
 
-			if target-folder == null
-				@go-root!
-				return
-
-			this.loading = true
-			this.update();
+			this.update({
+				fetching: true
+			});
 
 			this.api('drive/folders/show', {
-				folder_id: target-folder
-			}).then((folder) => {
-				this.folder = folder
-				this.hierarchyFolders = []
+				folder_id: target
+			}).then(folder => {
+				this.folder = folder;
+				this.hierarchyFolders = [];
 
-				x = (f) =>
-					@hierarchyFolders.unshift f
-					if f.parent?
-						x f.parent
+				const dive = folder => {
+					this.hierarchyFolders.unshift(folder);
+					if (folder.parent) dive(folder.parent);
+				};
 
-				if folder.parent?
-					x folder.parent
+				if (folder.parent) dive(folder.parent);
 
 				this.update();
 				this.load();
-			.catch (err, text-status) ->
-				console.error err
+			});
+		};
 
-		this.add-folder = (folder, unshift = false) => {
-			current = if this.folder? then this.folder.id else null
-			if current != folder.parent_id
-				return
+		this.addFolder = (folder, unshift = false) => {
+			const current = this.folder ? this.folder.id : null;
+			if (current != folder.parent_id) return;
 
-			if (this.folders.some (f) => f.id == folder.id)
-				exist = (this.folders.map (f) -> f.id).index-of folder.id
-				this.folders[exist] = folder
+			if (this.folders.some(f => f.id == folder.id)) {
+				const exist = this.folders.map(f => f.id).indexOf(folder.id);
+				this.folders[exist] = folder;
 				this.update();
-				return
+				return;
+			}
 
-			if unshift
-				this.folders.unshift folder
-			else
-				this.folders.push folder
+			if (unshift) {
+				this.folders.unshift(folder);
+			} else {
+				this.folders.push(folder);
+			}
 
 			this.update();
+		};
 
-		this.add-file = (file, unshift = false) => {
-			current = if this.folder? then this.folder.id else null
-			if current != file.folder_id
-				return
+		this.addFile = (file, unshift = false) => {
+			const current = this.folder ? this.folder.id : null;
+			if (current != file.folder_id) return;
 
-			if (this.files.some (f) => f.id == file.id)
-				exist = (this.files.map (f) -> f.id).index-of file.id
-				this.files[exist] = file
+			if (this.files.some(f => f.id == file.id)) {
+				const exist = this.files.map(f => f.id).indexOf(file.id);
+				this.files[exist] = file;
 				this.update();
-				return
+				return;
+			}
 
-			if unshift
-				this.files.unshift file
-			else
-				this.files.push file
+			if (unshift) {
+				this.files.unshift(file);
+			} else {
+				this.files.push(file);
+			}
 
 			this.update();
+		};
 
-		this.remove-folder = (folder) => {
-			if typeof folder == 'object' 
-				folder = folder.id
-			this.folders = this.folders.filter (f) -> f.id != folder
+		this.removeFolder = folder => {
+			if (typeof folder == 'object') folder = folder.id;
+			this.folders = this.folders.filter(f => f.id != folder);
 			this.update();
+		};
 
-		this.remove-file = (file) => {
-			if typeof file == 'object' 
-				file = file.id
-			this.files = this.files.filter (f) -> f.id != file
+		this.removeFile = file => {
+			if (typeof file == 'object') file = file.id;
+			this.files = this.files.filter(f => f.id != file);
 			this.update();
+		};
 
-		this.go-root = () => {
-			if this.folder != null
-				this.folder = null
-				this.hierarchyFolders = []
-				this.update();
-				this.load();
+		this.goRoot = () => {
+			// 既にrootにいるなら何もしない
+			if (this.folder == null) return;
+
+			this.update({
+				folder: null,
+				hierarchyFolders: []
+			});
+			this.load();
+		};
 
 		this.load = () => {
-			this.folders = []
-			this.files = []
-			this.more-folders = false
-			this.more-files = false
-			this.loading = true
-			this.update();
+			this.update({
+				folders: [],
+				files: [],
+				moreFolders: false,
+				moreFiles: false,
+				fetching: true
+			});
 
-			load-folders = null
-			load-files = null
+			let fetchedFolders = null;
+			let fetchedFiles = null;
 
-			folders-max = 30
-			files-max = 30
+			const foldersMax = 30;
+			const filesMax = 30;
 
 			// フォルダ一覧取得
 			this.api('drive/folders', {
-				folder_id: if this.folder? then this.folder.id else null
-				limit: folders-max + 1
-			}).then((folders) => {
-				if folders.length == folders-max + 1
-					this.more-folders = true
-					folders.pop!
-				load-folders := folders
-				complete!
-			.catch (err, text-status) =>
-				console.error err
+				folder_id: this.folder ? this.folder.id : null,
+				limit: foldersMax + 1
+			}).then(folders => {
+				if (folders.length == foldersMax + 1) {
+					this.moreFolders = true;
+					folders.pop();
+				}
+				fetchedFolders = folders;
+				complete();
+			});
 
 			// ファイル一覧取得
 			this.api('drive/files', {
-				folder_id: if this.folder? then this.folder.id else null
-				limit: files-max + 1
-			}).then((files) => {
-				if files.length == files-max + 1
-					this.more-files = true
-					files.pop!
-				load-files := files
-				complete!
-			.catch (err, text-status) =>
-				console.error err
+				folder_id: this.folder ? this.folder.id : null,
+				limit: filesMax + 1
+			}).then(files => {
+				if (files.length == filesMax + 1) {
+					this.moreFiles = true;
+					files.pop();
+				}
+				fetchedFiles = files;
+				complete();
+			});
 
-			flag = false
-			complete = =>
-				if flag
-					load-folders.forEach (folder) =>
-						this.addFolder folder
-					load-files.forEach (file) =>
-						this.addFile file
-					this.loading = false
-					this.update();
-				else
-					flag := true
+			let flag = false;
+			complete = () => {
+				if (flag) {
+					fetchedFolders.forEach(folder => this.addFolder);
+					fetchedFiles.forEach(file => this.addFile);
+					this.update({
+						fetching: false
+					});
+				} else {
+					flag = true;
+				}
+			};
+		};
 
 	</script>
 </mk-drive-browser>

From ea512a14b58911d281d0cad1db1aec8447d8a5f1 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 09:52:59 +0900
Subject: [PATCH 19/32] wip

---
 .../app/desktop/tags/post-status-graph.tag    | 75 -------------------
 1 file changed, 75 deletions(-)
 delete mode 100644 src/web/app/desktop/tags/post-status-graph.tag

diff --git a/src/web/app/desktop/tags/post-status-graph.tag b/src/web/app/desktop/tags/post-status-graph.tag
deleted file mode 100644
index 5f6a667eb..000000000
--- a/src/web/app/desktop/tags/post-status-graph.tag
+++ /dev/null
@@ -1,75 +0,0 @@
-<mk-post-status-graph>
-	<canvas ref="canv" width={ opts.width } height={ opts.height }></canvas>
-	<style>
-		:scope
-			display block
-
-			> canvas
-				margin 0 auto
-
-	</style>
-	<script>
-		this.mixin('api');
-		this.mixin('is-promise');
-
-		this.post = null
-		this.post-promise = if @is-promise this.opts.post then this.opts.post else Promise.resolve this.opts.post
-
-		this.on('mount', () => {
-			post <~ this.post-promise.then
-			this.post = post
-			this.update();
-
-			this.api('aggregation/posts/like', {
-				post_id: this.post.id
-				limit: 30days
-			}).then((likes) => {
-				likes = likes.reverse!
-
-				this.api('aggregation/posts/repost', {
-					post_id: this.post.id
-					limit: 30days
-				}).then((repost) => {
-					repost = repost.reverse!
-
-					this.api('aggregation/posts/reply', {
-						post_id: this.post.id
-						limit: 30days
-					}).then((replies) => {
-						replies = replies.reverse!
-
-						new Chart this.refs.canv, do
-							type: 'bar' 
-							data:
-								labels: likes.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
-								datasets: [
-									{
-										label: 'いいね' 
-										type: 'line' 
-										data: likes.map (x) => x.count
-										line-tension: 0
-										border-width: 2
-										fill: true
-										background-color: 'rgba(247, 121, 108, 0.2)'
-										point-background-color: '#fff' 
-										point-radius: 4
-										point-border-width: 2
-										border-color: '#F7796C' 
-									},
-									{
-										label: '返信' 
-										type: 'bar' 
-										data: replies.map (x) => x.count
-										background-color: '#555' 
-									},
-									{
-										label: 'Repost' 
-										type: 'bar' 
-										data: repost.map (x) => x.count
-										background-color: '#a2d61e' 
-									}
-								]
-							options:
-								responsive: false
-	</script>
-</mk-post-status-graph>

From 7921d3508a57e5d711a5d4a99b2a9f6b395c92ff Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 09:59:53 +0900
Subject: [PATCH 20/32] wip

---
 src/web/app/desktop/tags/input-dialog.tag | 28 ++++++++++++++---------
 src/web/app/mobile/tags/home.tag          |  2 ++
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/web/app/desktop/tags/input-dialog.tag b/src/web/app/desktop/tags/input-dialog.tag
index aa417f0a7..f343c4625 100644
--- a/src/web/app/desktop/tags/input-dialog.tag
+++ b/src/web/app/desktop/tags/input-dialog.tag
@@ -133,29 +133,35 @@
 			this.text.focus();
 
 			this.refs.window.on('closing', () => {
-				if @done
-					this.opts.on-ok @text.value
-				else
-					if this.opts.on-cancel?
-						this.opts.on-cancel!
+				if (this.done) {
+					this.opts.onOk(this.text.value);
+				} else {
+					if (this.opts.onCancel) this.opts.onCancel();
+				}
+			});
 
 			this.refs.window.on('closed', () => {
 				this.unmount();
 			});
+		});
 
 		this.cancel = () => {
-			this.done = false
+			this.done = false;
 			this.refs.window.close();
+		};
 
 		this.ok = () => {
-			if not @allow-empty and @text.value == '' then return
-			this.done = true
+			if (!this.allowEmpty && this.text.value == '') return;
+			this.done = true;
 			this.refs.window.close();
+		};
 
-		this.onKeydown = (e) => {
-			if e.which == 13 // Enter
+		this.onKeydown = e => {
+			if (e.which == 13) { // Enter
 				e.preventDefault();
 				e.stopPropagation();
-				@ok!
+				this.ok();
+			}
+		};
 	</script>
 </mk-input-dialog>
diff --git a/src/web/app/mobile/tags/home.tag b/src/web/app/mobile/tags/home.tag
index 0ca62cdb0..2edfd656e 100644
--- a/src/web/app/mobile/tags/home.tag
+++ b/src/web/app/mobile/tags/home.tag
@@ -16,5 +16,7 @@
 		this.on('mount', () => {
 			this.refs.tl.on('loaded', () => {
 				this.trigger('loaded');
+			});
+		});
 	</script>
 </mk-home>

From 3ea73a888d0bced98e0e92a8d92110d5b2fe46fd Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 11:44:53 +0900
Subject: [PATCH 21/32] wip

---
 src/web/app/desktop/tags/crop-window.tag      |  28 ++--
 src/web/app/desktop/tags/follow-button.tag    |  78 ++++++-----
 src/web/app/desktop/tags/home.tag             |  37 +++--
 .../tags/select-file-from-drive-window.tag    |  27 ++--
 .../desktop/tags/set-avatar-suggestion.tag    |   6 +-
 .../desktop/tags/set-banner-suggestion.tag    |   6 +-
 src/web/app/desktop/tags/timeline.tag         |  69 +++++----
 src/web/app/desktop/tags/user-timeline.tag    | 131 +++++++++---------
 src/web/app/desktop/tags/users-list.tag       |  79 ++++++-----
 src/web/app/mobile/tags/home-timeline.tag     |  48 ++++---
 src/web/app/mobile/tags/timeline.tag          |  67 +++++----
 src/web/app/mobile/tags/ui-header.tag         |  14 +-
 12 files changed, 334 insertions(+), 256 deletions(-)

diff --git a/src/web/app/desktop/tags/crop-window.tag b/src/web/app/desktop/tags/crop-window.tag
index 56845f24a..c5c186555 100644
--- a/src/web/app/desktop/tags/crop-window.tag
+++ b/src/web/app/desktop/tags/crop-window.tag
@@ -160,29 +160,35 @@
 	<script>
 		this.mixin('cropper');
 
-		this.image = this.opts.file
-		this.title = this.opts.title
-		this.aspect-ratio = this.opts.aspect-ratio
-		this.cropper = null
+		this.image = this.opts.file;
+		this.title = this.opts.title;
+		this.aspectRatio = this.opts.aspectRatio;
+		this.cropper = null;
 
 		this.on('mount', () => {
-			this.img = this.refs.window.refs.img
-			this.cropper = new @Cropper @img, do
-				aspect-ratio: @aspect-ratio
-				highlight: no
-				view-mode: 1
+			this.img = this.refs.window.refs.img;
+			this.cropper = new this.Cropper(this.img, {
+				aspectRatio: this.aspectRatio,
+				highlight: no,
+				viewMode: 1
+			});
+		});
 
 		this.ok = () => {
-			@cropper.get-cropped-canvas!.to-blob (blob) =>
-				this.trigger 'cropped' blob
+			this.cropper.getCroppedCanvas().toBlob(blob => {
+				this.trigger('cropped', blob);
 				this.refs.window.close();
+			});
+		};
 
 		this.skip = () => {
 			this.trigger('skiped');
 			this.refs.window.close();
+		};
 
 		this.cancel = () => {
 			this.trigger('canceled');
 			this.refs.window.close();
+		};
 	</script>
 </mk-crop-window>
diff --git a/src/web/app/desktop/tags/follow-button.tag b/src/web/app/desktop/tags/follow-button.tag
index 64055a158..1877e4a53 100644
--- a/src/web/app/desktop/tags/follow-button.tag
+++ b/src/web/app/desktop/tags/follow-button.tag
@@ -71,54 +71,70 @@
 		this.mixin('is-promise');
 		this.mixin('stream');
 
-		this.user = null
-		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
-		this.init = true
-		this.wait = false
+		this.user = null;
+		this.userPromise = this.isPromise(this.opts.user)
+			? this.opts.user
+			: Promise.resolve(this.opts.user);
+		this.init = true;
+		this.wait = false;
 
 		this.on('mount', () => {
-			this.user-promise}).then((user) => {
-				this.user = user
-				this.init = false
-				this.update();
-				this.stream.on 'follow' this.on-stream-follow
-				this.stream.on 'unfollow' this.on-stream-unfollow
+			this.userPromise.then(user => {
+				this.update({
+					init: false,
+					user: user
+				});
+				this.stream.on('follow', this.onStreamFollow);
+				this.stream.on('unfollow', this.onStreamUnfollow);
+			});
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'follow' this.on-stream-follow
-			this.stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off('follow', this.onStreamFollow);
+			this.stream.off('unfollow', this.onStreamUnfollow);
+		});
 
-		this.on-stream-follow = (user) => {
-			if user.id == this.user.id
-				this.user = user
-				this.update();
+		this.onStreamFollow = user => {
+			if (user.id == this.user.id) {
+				this.update({
+					user: user
+				});
+			}
+		};
 
-		this.on-stream-unfollow = (user) => {
-			if user.id == this.user.id
-				this.user = user
-				this.update();
+		this.onStreamUnfollow = user => {
+			if (user.id == this.user.id) {
+				this.update({
+					user: user
+				});
+			}
+		};
 
 		this.onclick = () => {
-			this.wait = true
-			if this.user.is_following
+			this.wait = true;
+			if (this.user.is_following) {
 				this.api('following/delete', {
 					user_id: this.user.id
 				}).then(() => {
-					this.user.is_following = false
-				.catch (err) ->
-					console.error err
+					this.user.is_following = false;
+				}).catch(err => {
+					console.error(err);
 				}).then(() => {
-					this.wait = false
+					this.wait = false;
 					this.update();
-			else
+				});
+			} else {
 				this.api('following/create', {
 					user_id: this.user.id
 				}).then(() => {
-					this.user.is_following = true
-				.catch (err) ->
-					console.error err
+					this.user.is_following = true;
+				}).catch(err => {
+					console.error(err);
 				}).then(() => {
-					this.wait = false
+					this.wait = false;
 					this.update();
+				});
+			}
+		};
 	</script>
 </mk-follow-button>
diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag
index 3d0d9d415..7a148d123 100644
--- a/src/web/app/desktop/tags/home.tag
+++ b/src/web/app/desktop/tags/home.tag
@@ -59,32 +59,39 @@
 	</style>
 	<script>
 		this.mixin('i');
-		this.mode = this.opts.mode || 'timeline' 
 
+		this.mode = this.opts.mode || 'timeline';
 		// https://github.com/riot/riot/issues/2080
-		if this.mode == '' then this.mode = 'timeline' 
+		if (this.mode == '') this.mode = 'timeline';
 
-		this.home = []
+		this.home = [];
 
 		this.on('mount', () => {
 			this.refs.tl.on('loaded', () => {
 				this.trigger('loaded');
+			});
 
-			this.I.data.home.forEach (widget) =>
-				try
-					el = document.createElement 'mk-' + widget.name + '-home-widget' 
-					switch widget.place
-						| 'left' => this.refs.left.appendChild el
-						| 'right' => this.refs.right.appendChild el
-					@home.push (riot.mount el, do
-						id: widget.id
+			this.I.data.home.forEach(widget => {
+				try {
+					const el = document.createElement(`mk-${widget.name}-home-widget`);
+					switch (widget.place) {
+						case 'left': this.refs.left.appendChild(el); break;
+						case 'right': this.refs.right.appendChild(el); break;
+					}
+					this.home.push(riot.mount(el, {
+						id: widget.id,
 						data: widget.data
-					.0)
-				catch e
+					})[0]);
+				} catch (e) {
 					// noop
+				}
+			});
+		});
 
 		this.on('unmount', () => {
-			@home.forEach (widget) =>
-				widget.unmount!
+			this.home.forEach(widget => {
+				widget.unmount();
+			});
+		});
 	</script>
 </mk-home>
diff --git a/src/web/app/desktop/tags/select-file-from-drive-window.tag b/src/web/app/desktop/tags/select-file-from-drive-window.tag
index 45ece233f..777073583 100644
--- a/src/web/app/desktop/tags/select-file-from-drive-window.tag
+++ b/src/web/app/desktop/tags/select-file-from-drive-window.tag
@@ -131,31 +131,38 @@
 
 	</style>
 	<script>
-		this.file = []
+		this.file = [];
 
-		this.multiple = if this.opts.multiple? then this.opts.multiple else false
-		this.title = this.opts.title || '<i class="fa fa-file-o"></i>ファイルを選択'
+		this.multiple = this.opts.multiple != null ? this.opts.multiple : false;
+		this.title = this.opts.title || '<i class="fa fa-file-o"></i>ファイルを選択';
 
 		this.on('mount', () => {
-			this.refs.window.refs.browser.on('selected', (file) => {
-				this.file = file
-				@ok!
+			this.refs.window.refs.browser.on('selected', file => {
+				this.file = file;
+				this.ok();
+			});
 
-			this.refs.window.refs.browser.on('change-selection', (files) => {
-				this.file = files
+			this.refs.window.refs.browser.on('change-selection', files => {
+				this.file = files;
 				this.update();
+			});
 
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
+		});
 
 		this.close = () => {
 			this.refs.window.close();
+		};
 
 		this.upload = () => {
-			this.refs.window.refs.browser.select-local-file!
+			this.refs.window.refs.browser.selectLocalFile();
+		};
 
 		this.ok = () => {
-			this.trigger 'selected' this.file
+			this.trigger('selected', this.file);
 			this.refs.window.close();
+		};
 	</script>
 </mk-select-file-from-drive-window>
diff --git a/src/web/app/desktop/tags/set-avatar-suggestion.tag b/src/web/app/desktop/tags/set-avatar-suggestion.tag
index ba44a7a33..335148ea5 100644
--- a/src/web/app/desktop/tags/set-avatar-suggestion.tag
+++ b/src/web/app/desktop/tags/set-avatar-suggestion.tag
@@ -35,11 +35,13 @@
 		this.mixin('update-avatar');
 
 		this.set = () => {
-			@update-avatar this.I
+			this.updateAvatar(this.I);
+		};
 
-		this.close = (e) => {
+		this.close = e => {
 			e.preventDefault();
 			e.stopPropagation();
 			this.unmount();
+		};
 	</script>
 </mk-set-avatar-suggestion>
diff --git a/src/web/app/desktop/tags/set-banner-suggestion.tag b/src/web/app/desktop/tags/set-banner-suggestion.tag
index fa735e4e4..deddc478c 100644
--- a/src/web/app/desktop/tags/set-banner-suggestion.tag
+++ b/src/web/app/desktop/tags/set-banner-suggestion.tag
@@ -35,11 +35,13 @@
 		this.mixin('update-banner');
 
 		this.set = () => {
-			@update-banner this.I
+			this.updateBanner(this.I);
+		};
 
-		this.close = (e) => {
+		this.close = e => {
 			e.preventDefault();
 			e.stopPropagation();
 			this.unmount();
+		};
 	</script>
 </mk-set-banner-suggestion>
diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag
index f63afabd4..a589adf5a 100644
--- a/src/web/app/desktop/tags/timeline.tag
+++ b/src/web/app/desktop/tags/timeline.tag
@@ -3,7 +3,9 @@
 		<mk-timeline-post post={ post }></mk-timeline-post>
 		<p class="date" if={ i != posts.length - 1 && post._date != posts[i + 1]._date }><span><i class="fa fa-angle-up"></i>{ post._datetext }</span><span><i class="fa fa-angle-down"></i>{ posts[i + 1]._datetext }</span></p>
 	</virtual>
-	<footer data-yield="footer"><yield from="footer"/></footer>
+	<footer data-yield="footer">
+		<yield from="footer"/>
+	</footer>
 	<style>
 		:scope
 			display block
@@ -44,36 +46,47 @@
 
 	</style>
 	<script>
-		this.posts = []
-
-		this.set-posts = (posts) => {
-			this.posts = posts
-			this.update();
-
-		this.prepend-posts = (posts) => {
-			posts.forEach (post) =>
-				this.posts.push post
-				this.update();
-
-		this.add-post = (post) => {
-			this.posts.unshift post
-			this.update();
-
-		this.clear = () => {
-			this.posts = []
-			this.update();
-
-		this.focus = () => {
-			this.root.children.0.focus();
+		this.posts = [];
 
 		this.on('update', () => {
-			this.posts.forEach (post) =>
-				date = (new Date post.created_at).getDate()
-				month = (new Date post.created_at).getMonth() + 1
-				post._date = date
-				post._datetext = month + '月 ' + date + '日'
+			this.posts.forEach(post => {
+				const date = new Date(post.created_at).getDate();
+				const month = new Date(post.created_at).getMonth() + 1;
+				post._date = date;
+				post._datetext = `${month}月 ${date}日`;
+			});
+		});
+
+		this.setPosts = posts => {
+			this.update({
+				posts: posts
+			});
+		};
+
+		this.prependPosts = posts => {
+			posts.forEach(post => {
+				this.posts.push(post);
+				this.update();
+			});
+		}
+
+		this.addPost = post => {
+			this.posts.unshift(post);
+			this.update();
+		};
 
 		this.tail = () => {
-			this.posts[this.posts.length - 1]
+			return this.posts[this.posts.length - 1];
+		};
+
+		this.clear = () => {
+			this.posts = [];
+			this.update();
+		};
+
+		this.focus = () => {
+			this.root.children[0].focus();
+		};
+
 	</script>
 </mk-timeline>
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index bc2e1744e..e8ff3dc05 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -50,89 +50,84 @@
 		this.mixin('is-promise');
 		this.mixin('get-post-summary');
 
-		this.user = null
-		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
-		this.is-loading = true
-		this.is-empty = false
-		this.more-loading = false
-		this.unread-count = 0
-		this.mode = 'default' 
+		this.user = null;
+		this.userPromise = this.isPromise(this.opts.user)
+			? this.opts.user
+			: Promise.resolve(this.opts.user);
+		this.isLoading = true;
+		this.isEmpty = false;
+		this.moreLoading = false;
+		this.unreadCount = 0;
+		this.mode = 'default';
 
 		this.on('mount', () => {
-			document.addEventListener 'visibilitychange' @window-onVisibilitychange, false
-			document.addEventListener 'keydown' this.on-document-keydown
-			window.addEventListener 'scroll' this.on-scroll
+			document.addEventListener('keydown', this.onDocumentKeydown);
+			window.addEventListener('scroll', this.onScroll);
 
-			this.user-promise}).then((user) => {
-				this.user = user
-				this.update();
+			this.userPromise.then(user => {
+				this.update({
+					user: user
+				});
 
-				@fetch =>
-					this.trigger('loaded');
+				this.fetch(() => this.trigger('loaded'));
+		});
 
 		this.on('unmount', () => {
-			document.removeEventListener 'visibilitychange' @window-onVisibilitychange
-			document.removeEventListener 'keydown' this.on-document-keydown
-			window.removeEventListener 'scroll' this.on-scroll
+			document.removeEventListener('keydown', this.onDocumentKeydown);
+			window.removeEventListener('scroll', this.onScroll);
+		});
 
-		this.on-document-keydown = (e) => {
-			tag = e.target.tag-name.to-lower-case!
-			if tag != 'input' and tag != 'textarea' 
-				if e.which == 84 // t
+		this.onDocumentKeydown = e => {
+			if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {
+				if (e.which == 84) { // [t]
 					this.refs.timeline.focus();
+				}
+			}
+		};
 
-		this.fetch = (cb) => {
+		this.fetch = cb => {
 			this.api('users/posts', {
-				user_id: this.user.id
-				with_replies: this.mode == 'with-replies' 
-			}).then((posts) => {
-				this.is-loading = false
-				this.is-empty = posts.length == 0
-				this.update();
-				this.refs.timeline.set-posts posts
-				if cb? then cb!
-			.catch (err) =>
-				console.error err
-				if cb? then cb!
+				user_id: this.user.id,
+				with_replies: this.mode == 'with-replies'
+			}).then(posts => {
+				this.update({
+					isLoading: false,
+					isEmpty: posts.length == 0
+				});
+				this.refs.timeline.setPosts(posts);
+				if (cb) cb();
+			});
+		};
 
 		this.more = () => {
-			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
-				return
-			this.more-loading = true
-			this.update();
+			if (this.moreLoading || this.isLoading || this.refs.timeline.posts.length == 0) return;
+			this.update({
+				moreLoading: true
+			});
 			this.api('users/posts', {
-				user_id: this.user.id
-				with_replies: this.mode == 'with-replies' 
-				max_id: this.refs.timeline.tail!.id
-			}).then((posts) => {
-				this.more-loading = false
-				this.update();
-				this.refs.timeline.prepend-posts posts
-			.catch (err) =>
-				console.error err
+				user_id: this.user.id,
+				with_replies: this.mode == 'with-replies',
+				max_id: this.refs.timeline.tail().id
+			}).then(posts => {
+				this.update({
+					moreLoading: false
+				});
+				this.refs.timeline.prependPosts(posts);
+			});
+		};
 
-		this.on-stream-post = (post) => {
-			this.is-empty = false
-			this.update();
-			this.refs.timeline.add-post post
+		this.onScroll = () => {
+			const current = window.scrollY + window.innerHeight;
+			if (current > document.body.offsetHeight - 16/*遊び*/) {
+				this.more();
+			}
+		};
 
-			if document.hidden
-				@unread-count++
-				document.title = '(' + @unread-count + ') ' + @get-post-summary post
-
-		this.window-onVisibilitychange = () => {
-			if !document.hidden
-				this.unread-count = 0
-				document.title = 'Misskey'
-
-		this.on-scroll = () => {
-			current = window.scrollY + window.inner-height
-			if current > document.body.offset-height - 16 // 遊び
-				@more!
-
-		this.set-mode = (mode) => {
-			@update do
+		this.setMode = mode => {
+			this.update({
 				mode: mode
-			@fetch!
+			});
+			this.fetch();
+		};
 	</script>
 </mk-user-timeline>
diff --git a/src/web/app/desktop/tags/users-list.tag b/src/web/app/desktop/tags/users-list.tag
index 2d85cd2ec..c94d0e228 100644
--- a/src/web/app/desktop/tags/users-list.tag
+++ b/src/web/app/desktop/tags/users-list.tag
@@ -1,7 +1,9 @@
 <mk-users-list>
 	<nav>
-		<div><span data-is-active={ mode == 'all' } onclick={ setMode.bind(this, 'all') }>すべて<span>{ opts.count }</span></span>
-			<!-- ↓ https://github.com/riot/riot/issues/2080--><span if={ SIGNIN && opts.youKnowCount != '' } data-is-active={ mode == 'iknow' } onclick={ setMode.bind(this, 'iknow') }>知り合い<span>{ opts.youKnowCount }</span></span>
+		<div>
+			<span data-is-active={ mode == 'all' } onclick={ setMode.bind(this, 'all') }>すべて<span>{ opts.count }</span></span>
+			<!-- ↓ https://github.com/riot/riot/issues/2080-->
+			<span if={ SIGNIN && opts.youKnowCount != '' } data-is-active={ mode == 'iknow' } onclick={ setMode.bind(this, 'iknow') }>知り合い<span>{ opts.youKnowCount }</span></span>
 		</div>
 	</nav>
 	<div class="users" if={ !fetching && users.length != 0 }>
@@ -9,8 +11,10 @@
 			<mk-list-user user={ this }></mk-list-user>
 		</div>
 	</div>
-	<button class="more" if={ !fetching && next != null } onclick={ more } disabled={ moreFetching }><span if={ !moreFetching }>もっと</span><span if={ moreFetching }>読み込み中
-			<mk-ellipsis></mk-ellipsis></span></button>
+	<button class="more" if={ !fetching && next != null } onclick={ more } disabled={ moreFetching }>
+		<span if={ !moreFetching }>もっと</span>
+		<span if={ moreFetching }>読み込み中<mk-ellipsis></mk-ellipsis></span>
+	</button>
 	<p class="no" if={ !fetching && users.length == 0 }>{ opts.noUsers }</p>
 	<p class="fetching" if={ fetching }><i class="fa fa-spinner fa-pulse fa-fw"></i>読み込んでいます
 		<mk-ellipsis></mk-ellipsis>
@@ -90,45 +94,48 @@
 	<script>
 		this.mixin('i');
 
-		this.limit = 30users
-		this.mode = 'all' 
+		this.limit = 30;
+		this.mode = 'all';
 
-		this.fetching = true
-		this.more-fetching = false
+		this.fetching = true;
+		this.moreFetching = false;
 
 		this.on('mount', () => {
-			@fetch =>
-				this.trigger('loaded');
+			this.fetch(() => this.trigger('loaded'));
+		});
 
-		this.fetch = (cb) => {
-			this.fetching = true
-			this.update();
-			obj <~ this.opts.fetch do
-				this.mode == 'iknow' 
-				@limit
-				null
-			this.users = obj.users
-			this.next = obj.next
-			this.fetching = false
-			this.update();
-			if cb? then cb!
+		this.fetch = cb => {
+			this.update({
+				fetching: true
+			});
+			this.opts.fetch(this.mode == 'iknow', this.limit, null, obj => {
+				this.update({
+					fetching: false,
+					users: obj.users,
+					next: obj.next
+				});
+				if (cb) cb();
+			});
+		};
 
 		this.more = () => {
-			this.more-fetching = true
-			this.update();
-			obj <~ this.opts.fetch do
-				this.mode == 'iknow' 
-				@limit
-				@cursor
-			this.users = this.users.concat obj.users
-			this.next = obj.next
-			this.more-fetching = false
-			this.update();
+			this.update({
+				moreFetching: true
+			});
+			this.opts.fetch(this.mode == 'iknow', this.limit, this.cursor, obj => {
+				this.update({
+					moreFetching: false,
+					users: this.users.concat(obj.users),
+					next: obj.next
+				});
+			});
+		};
 
-		this.set-mode = (mode) => {
-			@update do
+		this.setMode = mode => {
+			this.update({
 				mode: mode
-
-			@fetch!
+			});
+			this.fetch();
+		};
 	</script>
 </mk-users-list>
diff --git a/src/web/app/mobile/tags/home-timeline.tag b/src/web/app/mobile/tags/home-timeline.tag
index 0d617c841..2cb051f32 100644
--- a/src/web/app/mobile/tags/home-timeline.tag
+++ b/src/web/app/mobile/tags/home-timeline.tag
@@ -3,41 +3,49 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('api');
 		this.mixin('stream');
 
-		this.init = new Promise (res, rej) =>
-			this.api 'posts/timeline' 
-			}).then((posts) => {
-				res posts
+		this.init = new Promise((res, rej) => {
+			this.api('posts/timeline').then(posts => {
+				res(posts);
 				this.trigger('loaded');
+			});
+		});
 
 		this.on('mount', () => {
-			this.stream.on 'post' this.on-stream-post
-			this.stream.on 'follow' this.on-stream-follow
-			this.stream.on 'unfollow' this.on-stream-unfollow
+			this.stream.on('post', this.onStreamPost);
+			this.stream.on('follow', this.onStreamFollow);
+			this.stream.on('unfollow', this.onStreamUnfollow);
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'post' this.on-stream-post
-			this.stream.off 'follow' this.on-stream-follow
-			this.stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off('post', this.onStreamPost);
+			this.stream.off('follow', this.onStreamFollow);
+			this.stream.off('unfollow', this.onStreamUnfollow);
+		});
 
 		this.more = () => {
 			this.api('posts/timeline', {
-				max_id: this.refs.timeline.tail!.id
+				max_id: this.refs.timeline.tail().id
+			});
+		};
 
-		this.on-stream-post = (post) => {
-			this.is-empty = false
-			this.update();
-			this.refs.timeline.add-post post
+		this.onStreamPost = post => {
+			this.update({
+				isEmpty: false
+			});
+			this.refs.timeline.addPost(post);
+		};
 
-		this.on-stream-follow = () => {
-			@fetch!
+		this.onStreamFollow = () => {
+			this.fetch();
+		};
 
-		this.on-stream-unfollow = () => {
-			@fetch!
+		this.onStreamUnfollow = () => {
+			this.fetch();
+		};
 	</script>
 </mk-home-timeline>
diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag
index 06571e40e..421917d83 100644
--- a/src/web/app/mobile/tags/timeline.tag
+++ b/src/web/app/mobile/tags/timeline.tag
@@ -74,45 +74,58 @@
 
 	</style>
 	<script>
-		this.posts = []
-		this.init = true
-		this.fetching = false
-		this.can-fetch-more = true
+		this.posts = [];
+		this.init = true;
+		this.fetching = false;
+		this.canFetchMore = true;
 
 		this.on('mount', () => {
-			this.opts.init}).then((posts) => {
-				this.init = false
-				@set-posts posts
+			this.opts.init.then(posts => {
+				this.init = false;
+				this.setPosts(posts);
+			});
+		});
 
 		this.on('update', () => {
-			this.posts.forEach (post) =>
-				date = (new Date post.created_at).getDate()
-				month = (new Date post.created_at).getMonth() + 1
-				post._date = date
-				post._datetext = month + '月 ' + date + '日'
+			this.posts.forEach(post => {
+				const date = new Date(post.created_at).getDate();
+				const month = new Date(post.created_at).getMonth() + 1;
+				post._date = date;
+				post._datetext = `${month}月 ${date}日`;
+			});
+		});
 
 		this.more = () => {
-			if @init or @fetching or this.posts.length == 0 then return
-			this.fetching = true
-			this.update();
-			this.opts.more!}).then((posts) => {
-				this.fetching = false
-				this.prepend-posts posts
+			if (this.init || this.fetching || this.posts.length == 0) return;
+			this.update({
+				fetching: true
+			});
+			this.opts.more().then(posts => {
+				this.fetching = false;
+				this.prependPosts(posts);
+			});
+		};
 
-		this.set-posts = (posts) => {
-			this.posts = posts
-			this.update();
+		this.setPosts = posts => {
+			this.update({
+				posts: posts
+			});
+		};
 
-		this.prepend-posts = (posts) => {
-			posts.forEach (post) =>
-				this.posts.push post
+		this.prependPosts = posts => {
+			posts.forEach(post => {
+				this.posts.push(post);
 				this.update();
+			});
+		}
 
-		this.add-post = (post) => {
-			this.posts.unshift post
+		this.addPost = post => {
+			this.posts.unshift(post);
 			this.update();
+		};
 
 		this.tail = () => {
-			this.posts[this.posts.length - 1]
+			return this.posts[this.posts.length - 1];
+		};
 	</script>
 </mk-timeline>
diff --git a/src/web/app/mobile/tags/ui-header.tag b/src/web/app/mobile/tags/ui-header.tag
index 5cf2560d5..405db1897 100644
--- a/src/web/app/mobile/tags/ui-header.tag
+++ b/src/web/app/mobile/tags/ui-header.tag
@@ -89,16 +89,18 @@
 	</style>
 	<script>
 		this.mixin('ui');
-		this.mixin('openPostForm');
+		this.mixin('open-post-form');
 
 		this.on('mount', () => {
-			this.opts.ready!
+			this.opts.ready();
+		});
 
-		this.ui.on('title', (title) => {
-			if this.refs.title?
-				this.refs.title.innerHTML = title
+		this.ui.on('title', title => {
+			if (this.refs.title) this.refs.title.innerHTML = title;
+		});
 
 		this.post = () => {
-			this.openPostForm!
+			this.openPostForm();
+		};
 	</script>
 </mk-ui-header>

From e8378c2bb8e0611fe02dc4086ecea1fd4c9af3bd Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 17:52:10 +0900
Subject: [PATCH 22/32] wip

---
 .../desktop/tags/drive/base-contextmenu.tag   |  20 ++-
 .../app/desktop/tags/drive/browser-window.tag |  11 +-
 .../desktop/tags/drive/file-contextmenu.tag   |  58 +++---
 src/web/app/desktop/tags/drive/file.tag       |  90 +++++-----
 .../desktop/tags/drive/folder-contextmenu.tag |  28 +--
 src/web/app/desktop/tags/drive/folder.tag     | 167 ++++++++++--------
 src/web/app/desktop/tags/drive/nav-folder.tag |  99 ++++++-----
 7 files changed, 254 insertions(+), 219 deletions(-)

diff --git a/src/web/app/desktop/tags/drive/base-contextmenu.tag b/src/web/app/desktop/tags/drive/base-contextmenu.tag
index 06ccba6a2..2a95de0cd 100644
--- a/src/web/app/desktop/tags/drive/base-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/base-contextmenu.tag
@@ -13,26 +13,32 @@
 		</ul>
 	</mk-contextmenu>
 	<script>
-		this.browser = this.opts.browser
+		this.browser = this.opts.browser;
 
 		this.on('mount', () => {
 			this.refs.ctx.on('closed', () => {
 				this.trigger('closed');
 				this.unmount();
+			});
+		});
 
-		this.open = (pos) => {
-			this.refs.ctx.open pos
+		this.open = pos => {
+			this.refs.ctx.open(pos);
+		};
 
 		this.createFolder = () => {
-			this.browser.createFolder!
+			this.browser.createFolder();
 			this.refs.ctx.close();
+		};
 
 		this.upload = () => {
-			this.browser.select-local-file!
+			this.browser.selectLocalFile();
 			this.refs.ctx.close();
+		};
 
-		this.url-upload = () => {
-			this.browser.url-upload!
+		this.urlUpload = () => {
+			this.browser.urlUpload();
 			this.refs.ctx.close();
+		};
 	</script>
 </mk-drive-browser-base-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/browser-window.tag b/src/web/app/desktop/tags/drive/browser-window.tag
index f558b3d84..a658e3606 100644
--- a/src/web/app/desktop/tags/drive/browser-window.tag
+++ b/src/web/app/desktop/tags/drive/browser-window.tag
@@ -30,17 +30,22 @@
 	<script>
 		this.mixin('api');
 
-		this.folder = if this.opts.folder? then this.opts.folder else null
+		this.folder = this.opts.folder ? this.opts.folder : null;
 
 		this.on('mount', () => {
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
 
-			this.api 'drive' }).then((info) => {
-				@update do
+			this.api('drive').then(info => {
+				this.update({
 					usage: info.usage / info.capacity * 100
+				});
+			});
+		});
 
 		this.close = () => {
 			this.refs.window.close();
+		};
 	</script>
 </mk-drive-browser-window>
diff --git a/src/web/app/desktop/tags/drive/file-contextmenu.tag b/src/web/app/desktop/tags/drive/file-contextmenu.tag
index 933ae6db0..733ee853f 100644
--- a/src/web/app/desktop/tags/drive/file-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/file-contextmenu.tag
@@ -22,9 +22,6 @@
 					<li onclick={ parent.setBanner }>
 						<p>バナーに設定</p>
 					</li>
-					<li onclick={ parent.setWallpaper }>
-						<p>壁紙に設定</p>
-					</li>
 				</ul>
 			</li>
 			<li class="has-child">
@@ -46,52 +43,51 @@
 		this.mixin('input-dialog');
 		this.mixin('NotImplementedException');
 
-		this.browser = this.opts.browser
-		this.file = this.opts.file
+		this.browser = this.opts.browser;
+		this.file = this.opts.file;
 
 		this.on('mount', () => {
 			this.refs.ctx.on('closed', () => {
 				this.trigger('closed');
 				this.unmount();
+			});
+		});
 
-		this.open = (pos) => {
-			this.refs.ctx.open pos
+		this.open = pos => {
+			this.refs.ctx.open(pos);
+		};
 
 		this.rename = () => {
 			this.refs.ctx.close();
 
-			name <~ @input-dialog do
-				'ファイル名の変更'
-				'新しいファイル名を入力してください'
-				this.file.name
+			this.inputDialog('ファイル名の変更', '新しいファイル名を入力してください', this.file.name, name => {
+				this.api('drive/files/update', {
+					file_id: this.file.id,
+					name: name
+				})
+			});
+		};
 
-			this.api('drive/files/update', {
-				file_id: this.file.id
-				name: name
-			}).then(() => {
-				// something
-			.catch (err) =>
-				console.error err
-
-		this.copy-url = () => {
-			@NotImplementedException!
+		this.copyUrl = () => {
+			this.NotImplementedException();
+		};
 
 		this.download = () => {
 			this.refs.ctx.close();
+		};
 
-		this.set-avatar = () => {
+		this.setAvatar = () => {
 			this.refs.ctx.close();
-			@update-avatar this.I, null, this.file
+			this.updateAvatar(this.I, null, this.file);
+		};
 
-		this.set-banner = () => {
+		this.setBanner = () => {
 			this.refs.ctx.close();
-			@update-banner this.I, null, this.file
+			this.updateBanner(this.I, null, this.file);
+		};
 
-		this.set-wallpaper = () => {
-			this.refs.ctx.close();
-			@update-wallpaper this.I, null, this.file
-
-		this.add-app = () => {
-			@NotImplementedException!
+		this.addApp = () => {
+			this.NotImplementedException();
+		};
 	</script>
 </mk-drive-browser-file-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/file.tag b/src/web/app/desktop/tags/drive/file.tag
index e35d204b6..5d12f2419 100644
--- a/src/web/app/desktop/tags/drive/file.tag
+++ b/src/web/app/desktop/tags/drive/file.tag
@@ -148,62 +148,72 @@
 
 		this.mixin('i');
 
-		this.file = this.opts.file
-		this.browser = this.parent
+		this.file = this.opts.file;
+		this.browser = this.parent;
 
-		this.title = this.file.name + '\n' + this.file.type + ' ' + (@bytesToSize this.file.datasize)
+		this.title = `${this.file.name}\n${this.file.type} ${this.bytesToSize(this.file.datasize)}`;
 
-		this.is-contextmenu-showing = false
+		this.isContextmenuShowing = false;
 
 		this.onclick = () => {
-			if this.browser.multiple
-				if this.file._selected?
-					this.file._selected = !this.file._selected
-				else
-					this.file._selected = true
-				this.browser.trigger 'change-selection' this.browser.get-selection!
-			else
-				if this.file._selected
-					this.browser.trigger 'selected' this.file
-				else
-					this.browser.files.forEach (file) =>
-						file._selected = false
-					this.file._selected = true
-					this.browser.trigger 'change-selection' this.file
+			if (this.browser.multiple) {
+				if (this.file._selected != null) {
+					this.file._selected = !this.file._selected;
+				} else {
+					this.file._selected = true;
+				}
+				this.browser.trigger('change-selection', this.browser.getSelection());
+			} else {
+				if (this.file._selected) {
+					this.browser.trigger('selected', this.file);
+				} else {
+					this.browser.files.forEach(file => file._selected = false);
+					this.file._selected = true;
+					this.browser.trigger('change-selection', this.file);
+				}
+			}
+		};
 
-		this.oncontextmenu = (e) => {
+		this.oncontextmenu = e => {
 			e.preventDefault();
 			e.stopImmediatePropagation();
 
-			this.is-contextmenu-showing = true
-			this.update();
-			ctx = document.body.appendChild(document.createElement('mk-drive-browser-file-contextmenu'));
- 			ctx = riot.mount ctx, do
-				browser: this.browser
+			this.update({
+				isContextmenuShowing: true
+			});
+			const ctx = riot.mount(document.body.appendChild(document.createElement('mk-drive-browser-file-contextmenu')), {
+				browser: this.browser,
 				file: this.file
-			ctx = ctx.0
-			ctx.open do
-				x: e.pageX - window.pageXOffset
+			})[0];
+			ctx.open({
+				x: e.pageX - window.pageXOffset,
 				y: e.pageY - window.pageYOffset
+			});
 			ctx.on('closed', () => {
-				this.is-contextmenu-showing = false
-				this.update();
-			return false
+				this.update({
+					isContextmenuShowing: false
+				});
+			});
+			return false;
+		};
 
-		this.ondragstart = (e) => {
-			e.dataTransfer.effectAllowed = 'move' 
-			e.dataTransfer.set-data 'text' JSON.stringify do
-				type: 'file' 
-				id: this.file.id
+		this.ondragstart = e => {
+			e.dataTransfer.effectAllowed = 'move';
+			e.dataTransfer.setData('text', JSON.stringify({
+				type: 'file',
+				id: this.file.id,
 				file: this.file
-			this.is-dragging = true
+			});
+			this.isDragging = true;
 
 			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
 			// (=あなたの子供が、ドラッグを開始しましたよ)
-			this.browser.isDragSource = true
+			this.browser.isDragSource = true;
+		};
 
-		this.ondragend = (e) => {
-			this.is-dragging = false
-			this.browser.isDragSource = false
+		this.ondragend = e => {
+			this.isDragging = false;
+			this.browser.isDragSource = false;
+		};
 	</script>
 </mk-drive-browser-file>
diff --git a/src/web/app/desktop/tags/drive/folder-contextmenu.tag b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
index 582aa5e52..51e131f44 100644
--- a/src/web/app/desktop/tags/drive/folder-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/folder-contextmenu.tag
@@ -30,33 +30,33 @@
 			this.refs.ctx.on('closed', () => {
 				this.trigger('closed');
 				this.unmount();
+			});
+		};
 
 		this.move = () => {
-			this.browser.move this.folder.id
+			this.browser.move(this.folder.id);
 			this.refs.ctx.close();
+		};
 
 		this.newWindow = () => {
-			this.browser.newWindow this.folder.id
+			this.browser.newWindow(this.folder.id);
 			this.refs.ctx.close();
+		};
 
 		this.createFolder = () => {
 			this.browser.createFolder();
 			this.refs.ctx.close();
+		};
 
 		this.rename = () => {
 			this.refs.ctx.close();
 
-			name <~ @input-dialog do
-				'フォルダ名の変更'
-				'新しいフォルダ名を入力してください'
-				this.folder.name
-
-			this.api('drive/folders/update', {
-				folder_id: this.folder.id
-				name: name
-			}).then(() => {
-				// something
-			.catch (err) =>
-				console.error err
+			this.inputialog('フォルダ名の変更', '新しいフォルダ名を入力してください', this.folder.name, name => {
+				this.api('drive/folders/update', {
+					folder_id: this.folder.id,
+					name: name
+				});
+			});
+		};
 	</script>
 </mk-drive-browser-folder-contextmenu>
diff --git a/src/web/app/desktop/tags/drive/folder.tag b/src/web/app/desktop/tags/drive/folder.tag
index abc9368f4..1b804e97a 100644
--- a/src/web/app/desktop/tags/drive/folder.tag
+++ b/src/web/app/desktop/tags/drive/folder.tag
@@ -53,132 +53,149 @@
 		this.mixin('api');
 		this.mixin('dialog');
 
-		this.folder = this.opts.folder
-		this.browser = this.parent
+		this.folder = this.opts.folder;
+		this.browser = this.parent;
 
-		this.title = this.folder.name
-		this.hover = false
-		this.draghover = false
-		this.is-contextmenu-showing = false
+		this.title = this.folder.name;
+		this.hover = false;
+		this.draghover = false;
+		this.isContextmenuShowing = false;
 
 		this.onclick = () => {
-			this.browser.move this.folder
+			this.browser.move(this.folder);
+		};
 
 		this.onmouseover = () => {
-			this.hover = true
+			this.hover = true;
+		};
 
 		this.onmouseout = () => {
 			this.hover = false
+		};
 
-		this.ondragover = (e) => {
+		this.ondragover = e => {
 			e.preventDefault();
 			e.stopPropagation();
 
 			// 自分自身がドラッグされていない場合
-			if !@is-dragging
+			if (!this.isDragging) {
 				// ドラッグされてきたものがファイルだったら
-				if e.dataTransfer.effectAllowed == 'all' 
-					e.dataTransfer.dropEffect = 'copy' 
-				else
-					e.dataTransfer.dropEffect = 'move' 
-			else
+				if (e.dataTransfer.effectAllowed === 'all') {
+					e.dataTransfer.dropEffect = 'copy';
+				} else {
+					e.dataTransfer.dropEffect = 'move';
+				}
+			} else {
 				// 自分自身にはドロップさせない
-				e.dataTransfer.dropEffect = 'none' 
-			return false
+				e.dataTransfer.dropEffect = 'none';
+			}
+			return false;
+		};
 
 		this.ondragenter = () => {
-			if !@is-dragging
-				this.draghover = true
+			if (!this.isDragging) this.draghover = true;
+		};
 
 		this.ondragleave = () => {
-			this.draghover = false
+			this.draghover = false;
+		};
 
-		this.ondrop = (e) => {
+		this.ondrop = e => {
 			e.stopPropagation();
-			this.draghover = false
+			this.draghover = false;
 
 			// ファイルだったら
-			if e.dataTransfer.files.length > 0
-				Array.prototype.forEach.call e.dataTransfer.files, (file) =>
-					this.browser.upload file, this.folder
-				return false
+			if (e.dataTransfer.files.length > 0) {
+				e.dataTransfer.files.forEach(file => {
+					this.browser.upload(file, this.folder);
+				});
+				return false;
+			};
 
 			// データ取得
-			data = e.dataTransfer.get-data 'text'
-			if !data?
-				return false
+			const data = e.dataTransfer.getData('text');
+			if (data == null) return false;
 
 			// パース
-			obj = JSON.parse data
+			// TODO: Validate JSON
+			const obj = JSON.parse(data);
 
 			// (ドライブの)ファイルだったら
-			if obj.type == 'file' 
-				file = obj.id
-				this.browser.remove-file file
+			if (obj.type == 'file') {
+				const file = obj.id;
+				this.browser.removeFile(file);
 				this.api('drive/files/update', {
-					file_id: file
+					file_id: file,
 					folder_id: this.folder.id
-				}).then(() => {
-					// something
-				.catch (err, text-status) =>
-					console.error err
-
+				});
 			// (ドライブの)フォルダーだったら
-			else if obj.type == 'folder' 
-				folder = obj.id
+			} else if (obj.type == 'folder') {
+				const folder = obj.id;
 				// 移動先が自分自身ならreject
-				if folder == this.folder.id
-					return false
-				this.browser.remove-folder folder
+				if (folder == this.folder.id) return false;
+				this.browser.removeFolder(folder);
 				this.api('drive/folders/update', {
-					folder_id: folder
+					folder_id: folder,
 					parent_id: this.folder.id
 				}).then(() => {
 					// something
-				.catch (err) =>
-					if err == 'detected-circular-definition'
-						@dialog do
-							'<i class="fa fa-exclamation-triangle"></i>操作を完了できません'
-							'移動先のフォルダーは、移動するフォルダーのサブフォルダーです。'
-							[
-								text: 'OK' 
-							]
+				}).catch(err => {
+					switch (err) {
+						case 'detected-circular-definition':
+							this.dialog('<i class="fa fa-exclamation-triangle"></i>操作を完了できません',
+								'移動先のフォルダーは、移動するフォルダーのサブフォルダーです。', [{
+								text: 'OK'
+							}]);
+							break;
+						default:
+							alert('不明なエラー' + err);
+					}
+				});
+			}
 
-			return false
+			return false;
+		};
 
-		this.ondragstart = (e) => {
-			e.dataTransfer.effectAllowed = 'move' 
-			e.dataTransfer.set-data 'text' JSON.stringify do
-				type: 'folder' 
+		this.ondragstart = e => {
+			e.dataTransfer.effectAllowed = 'move';
+			e.dataTransfer.setData('text', JSON.stringify({
+				type: 'folder',
 				id: this.folder.id
-			this.is-dragging = true
+			}));
+			this.isDragging = true;
 
 			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
 			// (=あなたの子供が、ドラッグを開始しましたよ)
-			this.browser.isDragSource = true
+			this.browser.isDragSource = true;
+		};
 
-		this.ondragend = (e) => {
-			this.is-dragging = false
-			this.browser.isDragSource = false
+		this.ondragend = e => {
+			this.isDragging = false;
+			this.browser.isDragSource = false;
+		};
 
-		this.oncontextmenu = (e) => {
+		this.oncontextmenu = e => {
 			e.preventDefault();
 			e.stopImmediatePropagation();
 
-			this.is-contextmenu-showing = true
-			this.update();
-			ctx = document.body.appendChild(document.createElement('mk-drive-browser-folder-contextmenu'));
- 			ctx = riot.mount ctx, do
-				browser: this.browser
+			this.update({
+				isContextmenuShowing: true
+			});
+			const ctx = riot.mount(document.body.appendChild(document.createElement('mk-drive-browser-folder-contextmenu')), {
+				browser: this.browser,
 				folder: this.folder
-			ctx = ctx.0
-			ctx.open do
-				x: e.pageX - window.pageXOffset
+			})[0];
+			ctx.open({
+				x: e.pageX - window.pageXOffset,
 				y: e.pageY - window.pageYOffset
+			});
 			ctx.on('closed', () => {
-				this.is-contextmenu-showing = false
-				this.update();
+				this.update({
+					isContextmenuShowing: false
+				});
+			});
 
-			return false
+			return false;
+		};
 	</script>
 </mk-drive-browser-folder>
diff --git a/src/web/app/desktop/tags/drive/nav-folder.tag b/src/web/app/desktop/tags/drive/nav-folder.tag
index b485ddb53..e961ac491 100644
--- a/src/web/app/desktop/tags/drive/nav-folder.tag
+++ b/src/web/app/desktop/tags/drive/nav-folder.tag
@@ -10,88 +10,89 @@
 
 		// Riotのバグでnullを渡しても""になる
 		// https://github.com/riot/riot/issues/2080
-		#this.folder = this.opts.folder
-		this.folder = if this.opts.folder? and this.opts.folder != '' then this.opts.folder else null
-		this.browser = this.parent
+		//this.folder = this.opts.folder
+		this.folder = this.opts.folder && this.opts.folder != '' ? this.opts.folder : null;
+		this.browser = this.parent;
 
-		this.hover = false
+		this.hover = false;
 
 		this.onclick = () => {
-			this.browser.move this.folder
+			this.browser.move(this.folder);
+		};
 
 		this.onmouseover = () => {
 			this.hover = true
+		};
 
 		this.onmouseout = () => {
 			this.hover = false
+		};
 
-		this.ondragover = (e) => {
+		this.ondragover = e => {
 			e.preventDefault();
 			e.stopPropagation();
 
 			// このフォルダがルートかつカレントディレクトリならドロップ禁止
-			if this.folder == null and this.browser.folder == null
-				e.dataTransfer.dropEffect = 'none' 
+			if (this.folder == null && this.browser.folder == null) {
+				e.dataTransfer.dropEffect = 'none';
 			// ドラッグされてきたものがファイルだったら
-			else if e.dataTransfer.effectAllowed == 'all' 
-				e.dataTransfer.dropEffect = 'copy' 
-			else
-				e.dataTransfer.dropEffect = 'move' 
-			return false
+			} else if (e.dataTransfer.effectAllowed == 'all') {
+				e.dataTransfer.dropEffect = 'copy';
+			} else {
+				e.dataTransfer.dropEffect = 'move';
+			}
+			return false;
+		};
 
 		this.ondragenter = () => {
-			if this.folder != null or this.browser.folder != null
-				this.draghover = true
+			if (this.folder || this.browser.folder) this.draghover = true;
+		};
 
 		this.ondragleave = () => {
-			if this.folder != null or this.browser.folder != null
-				this.draghover = false
+			if (this.folder || this.browser.folder) this.draghover = false;
+		};
 
-		this.ondrop = (e) => {
+		this.ondrop = e => {
 			e.stopPropagation();
-			this.draghover = false
+			this.draghover = false;
 
 			// ファイルだったら
-			if e.dataTransfer.files.length > 0
-				Array.prototype.forEach.call e.dataTransfer.files, (file) =>
-					this.browser.upload file, this.folder
-				return false
+			if (e.dataTransfer.files.length > 0) {
+				e.dataTransfer.files.forEach(file => {
+					this.browser.upload(file, this.folder);
+				});
+				return false;
+			};
 
 			// データ取得
-			data = e.dataTransfer.get-data 'text'
-			if !data?
-				return false
+			const data = e.dataTransfer.getData('text');
+			if (data == null) return false;
 
 			// パース
-			obj = JSON.parse data
+			// TODO: Validate JSON
+			const obj = JSON.parse(data);
 
 			// (ドライブの)ファイルだったら
-			if obj.type == 'file' 
-				file = obj.id
-				this.browser.remove-file file
+			if (obj.type == 'file') {
+				const file = obj.id;
+				this.browser.removeFile(file);
 				this.api('drive/files/update', {
-					file_id: file
-					folder_id: if this.folder? then this.folder.id else null
-				}).then(() => {
-					// something
-				.catch (err, text-status) =>
-					console.error err
-
+					file_id: file,
+					folder_id: this.folder ? this.folder.id : null
+				});
 			// (ドライブの)フォルダーだったら
-			else if obj.type == 'folder' 
-				folder = obj.id
+			} else if (obj.type == 'folder') {
+				const folder = obj.id;
 				// 移動先が自分自身ならreject
-				if this.folder? and folder == this.folder.id
-					return false
-				this.browser.remove-folder folder
+				if (this.folder && folder == this.folder.id) return false;
+				this.browser.removeFolder(folder);
 				this.api('drive/folders/update', {
-					folder_id: folder
-					parent_id: if this.folder? then this.folder.id else null
-				}).then(() => {
-					// something
-				.catch (err, text-status) =>
-					console.error err
+					folder_id: folder,
+					parent_id: this.folder ? this.folder.id : null
+				});
+			}
 
-			return false
+			return false;
+		};
 	</script>
 </mk-drive-browser-nav-folder>

From 8fd6f24ee6665124aadec5712591ae0a8375e602 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 18:36:43 +0900
Subject: [PATCH 23/32] wip

---
 .../desktop/tags/home-widgets/calendar.tag    |  48 ++++----
 .../desktop/tags/home-widgets/mentions.tag    |  94 ++++++++-------
 src/web/app/desktop/tags/home-widgets/nav.tag |   4 -
 .../tags/home-widgets/notifications.tag       |   5 +-
 .../tags/home-widgets/photo-stream.tag        |  35 +++---
 .../app/desktop/tags/home-widgets/profile.tag |  10 +-
 .../desktop/tags/home-widgets/rss-reader.tag  |  34 +++---
 .../desktop/tags/home-widgets/timeline.tag    | 109 ++++++++++--------
 .../app/desktop/tags/home-widgets/tips.tag    |  43 +++----
 .../tags/home-widgets/user-recommendation.tag |  56 +++++----
 10 files changed, 231 insertions(+), 207 deletions(-)

diff --git a/src/web/app/desktop/tags/home-widgets/calendar.tag b/src/web/app/desktop/tags/home-widgets/calendar.tag
index acf8e8c73..2a455edff 100644
--- a/src/web/app/desktop/tags/home-widgets/calendar.tag
+++ b/src/web/app/desktop/tags/home-widgets/calendar.tag
@@ -108,41 +108,43 @@
 	<script>
 		this.draw = () => {
 			const now = new Date();
-			nd = now.getDate()
-			nm = now.getMonth()
-			ny = now.getFullYear()
+			const nd = now.getDate();
+			const nm = now.getMonth();
+			const ny = now.getFullYear();
 
-			this.year = ny
-			this.month = nm + 1
-			this.day = nd
-			this.week-day = [\日 '月' \火 '水' \木 '金' \土][now.get-day!]
+			this.year = ny;
+			this.month = nm + 1;
+			this.day = nd;
+			this.weekDay = ['日', '月', '火', '水' '木', '金', '土'][now.getDay()];
 
-			@day-numer   = (now - (new Date ny, nm, nd))
-			@day-denom   = 1000ms * 60s * 60m * 24h
-			this.month-numer = (now - (new Date ny, nm, 1))
-			this.month-denom = (new Date ny, nm + 1,  1) - (new Date ny, nm, 1)
-			@year-numer  = (now - (new Date ny, 0, 1))
-			@year-denom  = (new Date ny + 1, 0,  1) - (new Date ny, 0, 1)
+			this.dayNumer   = now - new Date(ny, nm, nd);
+			this.dayDenom   = 1000/*ms*/ * 60/*s*/ * 60/*m*/ * 24/*h*/;
+			this.monthNumer = now - new Date(ny, nm, 1);
+			this.monthDenom = new Date(ny, nm + 1, 1) - new Date(ny, nm, 1);
+			this.yearNumer  = now - new Date(ny, 0, 1);
+			this.yearDenom  = new Date(ny + 1, 0, 1) - new Date(ny, 0, 1);
 
-			@day-p   = @day-numer   / @day-denom   * 100
-			this.month-p = @month-numer / @month-denom * 100
-			@year-p  = @year-numer  / @year-denom  * 100
+			this.dayP   = this.dayNumer   / this.dayDenom   * 100;
+			this.monthP = this.monthNumer / this.monthDenom * 100;
+			this.yearP  = this.yearNumer  / this.yearDenom  * 100;
 
-			this.is-holiday = 
-				(now.get-day! == 0 or now.get-day! == 6)
+			this.isHoliday = now.getDay() == 0 || now.getDay() == 6;
 
 			this.special = 
-				| nm == 0 and nd == 1 => 'on-new-years-day' 
-				| _ => false
+				nm == 0 && nd == 1 ? 'on-new-years-day' :
+				false;
 
 			this.update();
+		};
 
-		@draw!
+		this.draw();
 
 		this.on('mount', () => {
-			this.clock = setInterval @draw, 1000ms
+			this.clock = setInterval(this.draw, 1000);
+		});
 
 		this.on('unmount', () => {
-			clearInterval @clock
+			clearInterval(this.clock);
+		});
 	</script>
 </mk-calendar-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/mentions.tag b/src/web/app/desktop/tags/home-widgets/mentions.tag
index 4ae17647f..6e6d891cb 100644
--- a/src/web/app/desktop/tags/home-widgets/mentions.tag
+++ b/src/web/app/desktop/tags/home-widgets/mentions.tag
@@ -49,64 +49,70 @@
 		this.mixin('i');
 		this.mixin('api');
 
-		this.is-loading = true
-		this.is-empty = false
-		this.more-loading = false
-		this.mode = 'all' 
+		this.isLoading = true;
+		this.isEmpty = false;
+		this.moreLoading = false;
+		this.mode = 'all';
 
 		this.on('mount', () => {
-			document.addEventListener 'keydown' this.on-document-keydown
-			window.addEventListener 'scroll' this.on-scroll
+			document.addEventListener('keydown', this.onDocumentKeydown);
+			window.addEventListener('scroll', this.onScroll);
 
-			@fetch =>
-				this.trigger('loaded');
+			this.fetch(() => this.trigger('loaded'));
+		});
 
 		this.on('unmount', () => {
-			document.removeEventListener 'keydown' this.on-document-keydown
-			window.removeEventListener 'scroll' this.on-scroll
+			document.removeEventListener('keydown', this.onDocumentKeydown);
+			window.removeEventListener('scroll', this.onScroll);
+		});
 
-		this.on-document-keydown = (e) => {
-			tag = e.target.tag-name.to-lower-case!
-			if tag != 'input' and tag != 'textarea' 
-				if e.which == 84 // t
+		this.onDocumentKeydown = e => {
+			if (e.target.tagName != 'INPUT' && tag != 'TEXTAREA') {
+				if (e.which == 84) { // t
 					this.refs.timeline.focus();
+				}
+			}
+		};
 
-		this.fetch = (cb) => {
+		this.fetch = cb => {
 			this.api('posts/mentions', {
-				following: this.mode == 'following' 
-			}).then((posts) => {
-				this.is-loading = false
-				this.is-empty = posts.length == 0
-				this.update();
-				this.refs.timeline.set-posts posts
-				if cb? then cb!
-			.catch (err) =>
-				console.error err
-				if cb? then cb!
+				following: this.mode == 'following'
+			}).then(posts => {
+				this.update({
+					isLoading: false,
+					isEmpty: posts.length == 0
+				});
+				this.refs.timeline.setPosts(posts);
+				if (cb) cb();
+			});
+		};
 
 		this.more = () => {
-			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
-				return
-			this.more-loading = true
-			this.update();
+			if (this.moreLoading || this.isLoading || this.refs.timeline.posts.length == 0) return;
+			this.update({
+				moreLoading: true
+			});
 			this.api('posts/mentions', {
-				following: this.mode == 'following' 
-				max_id: this.refs.timeline.tail!.id
-			}).then((posts) => {
-				this.more-loading = false
-				this.update();
-				this.refs.timeline.prepend-posts posts
-			.catch (err) =>
-				console.error err
+				following: this.mode == 'following',
+				max_id: this.refs.timeline.tail().id
+			}).then(posts => {
+				this.update({
+					moreLoading: false
+				});
+				this.refs.timeline.prependPosts(posts);
+			});
+		};
 
-		this.on-scroll = () => {
-			current = window.scrollY + window.inner-height
-			if current > document.body.offset-height - 8
-				@more!
+		this.onScroll = () => {
+			const current = window.scrollY + window.innerHeight;
+			if (current > document.body.offsetHeight - 8) this.more();
+		};
 
-		this.set-mode = (mode) => {
-			@update do
+		this.setMode = mode => {
+			this.update({
 				mode: mode
-			@fetch!
+			});
+			this.fetch();
+		};
 	</script>
 </mk-mentions-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/nav.tag b/src/web/app/desktop/tags/home-widgets/nav.tag
index a792299a5..67affc75f 100644
--- a/src/web/app/desktop/tags/home-widgets/nav.tag
+++ b/src/web/app/desktop/tags/home-widgets/nav.tag
@@ -13,9 +13,5 @@
 			i
 				color #ccc
 
-			
-
-			
-
 	</style>
 </mk-nav-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/notifications.tag b/src/web/app/desktop/tags/home-widgets/notifications.tag
index 12520e95a..5ed26b5d7 100644
--- a/src/web/app/desktop/tags/home-widgets/notifications.tag
+++ b/src/web/app/desktop/tags/home-widgets/notifications.tag
@@ -44,7 +44,8 @@
 	</style>
 	<script>
 		this.settings = () => {
-			w = riot.mount document.body.appendChild document.createElement 'mk-settings-window' .0
-			w.switch 'notification' 
+			const w = riot.mount(document.body.appendChild(document.createElement('mk-settings-window')[0];
+			w.switch('notification');
+		};
 	</script>
 </mk-notifications-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/photo-stream.tag b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
index 3ebbf6a1e..7cbb07b4d 100644
--- a/src/web/app/desktop/tags/home-widgets/photo-stream.tag
+++ b/src/web/app/desktop/tags/home-widgets/photo-stream.tag
@@ -60,28 +60,33 @@
 		this.mixin('api');
 		this.mixin('stream');
 
-		this.images = []
-		this.initializing = true
+		this.images = [];
+		this.initializing = true;
 
 		this.on('mount', () => {
-			this.stream.on 'drive_file_created' this.onStreamDriveFileCreated
+			this.stream.on('drive_file_created', this.onStreamDriveFileCreated);
 
 			this.api('drive/stream', {
-				type: 'image/*'
-				limit: 9images
-			}).then((images) => {
-				this.initializing = false
-				this.images = images
-				this.update();
+				type: 'image/*',
+				limit: 9
+			}).then(images => {
+				this.update({
+					initializing: false,
+					images: images
+				});
+			});
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'drive_file_created' this.onStreamDriveFileCreated
+			this.stream.off('drive_file_created', this.onStreamDriveFileCreated);
+		});
 
-		this.onStreamDriveFileCreated = (file) => {
-			if /^image\/.+$/.test file.type
-				@images.unshift file
-				if @images.length > 9
-					@images.pop!
+		this.onStreamDriveFileCreated = file => {
+			if (/^image\/.+$/.test(file.type)) {
+				this.images.unshift(file);
+				if (this.images.length > 9) this.images.pop();
 				this.update();
+			}
+		};
 	</script>
 </mk-photo-stream-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/profile.tag b/src/web/app/desktop/tags/home-widgets/profile.tag
index 72b2c18c3..8ee218614 100644
--- a/src/web/app/desktop/tags/home-widgets/profile.tag
+++ b/src/web/app/desktop/tags/home-widgets/profile.tag
@@ -46,10 +46,12 @@
 		this.mixin('update-avatar');
 		this.mixin('update-banner');
 
-		this.set-avatar = () => {
-			@update-avatar this.I
+		this.setAvatar = () => {
+			this.updateAvatar(this.I);
+		};
 
-		this.set-banner = () => {
-			@update-banner this.I
+		this.setBanner = () => {
+			this.updateBanner(this.I);
+		};
 	</script>
 </mk-profile-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/rss-reader.tag b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
index 98af55cb5..c8700a8b6 100644
--- a/src/web/app/desktop/tags/home-widgets/rss-reader.tag
+++ b/src/web/app/desktop/tags/home-widgets/rss-reader.tag
@@ -67,28 +67,32 @@
 		this.mixin('api');
 		this.mixin('NotImplementedException');
 
-		this.url = 'http://news.yahoo.co.jp/pickup/rss.xml'
-		this.items = []
-		this.initializing = true
+		this.url = 'http://news.yahoo.co.jp/pickup/rss.xml';
+		this.items = [];
+		this.initializing = true;
 
 		this.on('mount', () => {
-			@fetch!
-			this.clock = setInterval @fetch, 60000ms
+			this.fetch();
+			this.clock = setInterval(this.fetch, 60000);
+		});
 
 		this.on('unmount', () => {
-			clearInterval @clock
+			clearInterval(this.clock);
+		});
 
 		this.fetch = () => {
-			this.api CONFIG.url + '/api:rss' do
-				url: @url
-			}).then((feed) => {
-				this.items = feed.rss.channel.item
-				this.initializing = false
-				this.update();
-			.catch (err) ->
-				console.error err
+			this.api(CONFIG.url + '/api:rss', {
+				url: this.url
+			}).then(feed => {
+				this.update({
+					initializing: false,
+					items: feed.rss.channel.item
+				});
+			});
+		};
 
 		this.settings = () => {
-			@NotImplementedException!
+			this.NotImplementedException();
+		};
 	</script>
 </mk-rss-reader-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index 69417aa83..138ff5ed1 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -36,76 +36,83 @@
 		this.mixin('api');
 		this.mixin('stream');
 
-		this.is-loading = true
-		this.is-empty = false
-		this.more-loading = false
-		this.no-following = this.I.following_count == 0
+		this.isLoading = true;
+		this.isEmpty = false;
+		this.moreLoading = false;
+		this.noFollowing = this.I.following_count == 0;
 
 		this.on('mount', () => {
-			this.stream.on 'post' this.on-stream-post
-			this.stream.on 'follow' this.on-stream-follow
-			this.stream.on 'unfollow' this.on-stream-unfollow
+			this.stream.on('post', this.onStreamPost);
+			this.stream.on('follow', this.onStreamFollow);
+			this.stream.on('unfollow', this.onStreamUnfollow);
 
-			document.addEventListener 'keydown' this.on-document-keydown
-			window.addEventListener 'scroll' this.on-scroll
+			document.addEventListener('keydown', this.onDocumentKeydown);
+			window.addEventListener('scroll', this.onScroll);
 
-			@load =>
-				this.trigger('loaded');
+			this.load(() => this.trigger('loaded'));
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'post' this.on-stream-post
-			this.stream.off 'follow' this.on-stream-follow
-			this.stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off('post', this.onStreamPost);
+			this.stream.off('follow', this.onStreamFollow);
+			this.stream.off('unfollow', this.onStreamUnfollow);
 
-			document.removeEventListener 'keydown' this.on-document-keydown
-			window.removeEventListener 'scroll' this.on-scroll
+			document.removeEventListener('keydown', this.onDocumentKeydown);
+			window.removeEventListener('scroll', this.onScroll);
+		});
 
-		this.on-document-keydown = (e) => {
-			tag = e.target.tag-name.to-lower-case!
-			if tag != 'input' and tag != 'textarea' 
-				if e.which == 84 // t
+		this.onDocumentKeydown = e => {
+			if (e.target.tagName != 'INPUT' && tag != 'TEXTAREA') {
+				if (e.which == 84) { // t
 					this.refs.timeline.focus();
+				}
+			}
+		};
 
 		this.load = (cb) => {
-			this.api 'posts/timeline' 
-			}).then((posts) => {
-				this.is-loading = false
-				this.is-empty = posts.length == 0
-				this.update();
-				this.refs.timeline.set-posts posts
-				if cb? then cb!
-			.catch (err) =>
-				console.error err
-				if cb? then cb!
+			this.api('posts/timeline').then(posts => {
+				this.update({
+					isLoading: false,
+					isEmpty: posts.length == 0
+				});
+				this.refs.timeline.setPosts(posts);
+				if (cb) cb();
+			});
+		};
 
 		this.more = () => {
-			if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
-				return
-			this.more-loading = true
-			this.update();
+			if (this.moreLoading || this.isLoading || this.refs.timeline.posts.length == 0) return;
+			this.update({
+				moreLoading: true
+			});
 			this.api('posts/timeline', {
-				max_id: this.refs.timeline.tail!.id
-			}).then((posts) => {
-				this.more-loading = false
-				this.update();
-				this.refs.timeline.prepend-posts posts
-			.catch (err) =>
-				console.error err
+				max_id: this.refs.timeline.tail().id
+			}).then(posts => {
+				this.update({
+					moreLoading: false
+				});
+				this.refs.timeline.prependPosts(posts);
+			});
+		};
 
-		this.on-stream-post = (post) => {
-			this.is-empty = false
-			this.update();
-			this.refs.timeline.add-post post
+		this.onStreamPost = post => {
+			this.update({
+				isEmpty: false
+			});
+			this.refs.timeline.addPost(post);
+		};
 
-		this.on-stream-follow = () => {
+		this.onStreamFollow = () => {
 			this.load();
+		};
 
-		this.on-stream-unfollow = () => {
+		this.onStreamUnfollow = () => {
 			this.load();
+		};
 
-		this.on-scroll = () => {
-			current = window.scrollY + window.inner-height
-			if current > document.body.offset-height - 8
-				@more!
+		this.onScroll = () => {
+			const current = window.scrollY + window.innerHeight;
+			if (current > document.body.offsetHeight - 8) this.more();
+		};
 	</script>
 </mk-timeline-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/tips.tag b/src/web/app/desktop/tags/home-widgets/tips.tag
index ff7516f33..27268f3ed 100644
--- a/src/web/app/desktop/tags/home-widgets/tips.tag
+++ b/src/web/app/desktop/tags/home-widgets/tips.tag
@@ -30,42 +30,45 @@
 	</style>
 	<script>
 		this.tips = [
-			'<kbd>t</kbd>でタイムラインにフォーカスできます'
-			'<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます'
-			'投稿フォームにはファイルをドラッグ&ドロップできます'
-			'投稿フォームにクリップボードにある画像データをペーストできます'
-			'ドライブにファイルをドラッグ&ドロップしてアップロードできます'
-			'ドライブでファイルをドラッグしてフォルダ移動できます'
-			'ドライブでフォルダをドラッグしてフォルダ移動できます'
-			'ホームをカスタマイズできます(準備中)'
+			'<kbd>t</kbd>でタイムラインにフォーカスできます',
+			'<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます',
+			'投稿フォームにはファイルをドラッグ&ドロップできます',
+			'投稿フォームにクリップボードにある画像データをペーストできます',
+			'ドライブにファイルをドラッグ&ドロップしてアップロードできます',
+			'ドライブでファイルをドラッグしてフォルダ移動できます',
+			'ドライブでフォルダをドラッグしてフォルダ移動できます',
+			'ホームをカスタマイズできます(準備中)',
 			'MisskeyはMIT Licenseです'
 		]
 
 		this.on('mount', () => {
-			@set!
-			this.clock = setInterval @change, 20000ms
+			this.set();
+			this.clock = setInterval(this.change, 20000);
+		});
 
 		this.on('unmount', () => {
-			clearInterval @clock
+			clearInterval(this.clock);
+		});
 
 		this.set = () => {
-			this.refs.text.innerHTML = @tips[Math.floor Math.random! * @tips.length]
-			this.update();
+			this.refs.text.innerHTML = this.tips[Math.floor(Math.random() * this.tips.length)];
+		};
 
 		this.change = () => {
 			Velocity(this.refs.tip, {
 				opacity: 0
 			}, {
-				duration: 500ms
-				easing: 'linear' 
-				complete: @set
-			}
+				duration: 500,
+				easing: 'linear',
+				complete: this.set
+			});
 
 			Velocity(this.refs.tip, {
 				opacity: 1
 			}, {
-				duration: 500ms
-				easing: 'linear' 
-			}
+				duration: 500,
+				easing: 'linear'
+			});
+		};
 	</script>
 </mk-tips-home-widget>
diff --git a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
index 63a8d1571..517d206a4 100644
--- a/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
+++ b/src/web/app/desktop/tags/home-widgets/user-recommendation.tag
@@ -112,41 +112,39 @@
 		this.mixin('api');
 		this.mixin('user-preview');
 
-		this.users = null
-		this.loading = true
+		this.users = null;
+		this.loading = true;
 
-		this.limit = 3users
-		this.page = 0
+		this.limit = 3;
+		this.page = 0;
 
 		this.on('mount', () => {
-			@fetch!
-			this.clock = setInterval =>
-				if this.users.length < @limit
-					@fetch true
-			, 60000ms
+			this.fetch();
+		});
 
-		this.on('unmount', () => {
-			clearInterval @clock
-
-		this.fetch = (quiet = false) => {
-			this.loading = true
-			this.users = null
-			if not quiet then this.update();
+		this.fetch = () => {
+			this.update({
+				loading: true,
+				users: null
+			});
 			this.api('users/recommendation', {
-				limit: @limit
-				offset: @limit * this.page
-			}).then((users) => {
-				this.loading = false
-				this.users = users
-				this.update();
-			.catch (err, text-status) ->
-				console.error err
+				limit: this.limit,
+				offset: this.limit * this.page
+			}).then(users => {
+				this.update({
+					loading: false,
+					users: users
+				});
+			});
+		};
 
 		this.refresh = () => {
-			if this.users.length < @limit
-				this.page = 0
-			else
-				this.page++
-			@fetch!
+			if (this.users.length < this.limit) {
+				this.page = 0;
+			} else {
+				this.page++;
+			}
+			this.fetch();
+		};
 	</script>
 </mk-user-recommendation-home-widget>

From 2a9d9643aaaf39f61b3e4bc6c8c40f89ac27610e Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 19:10:07 +0900
Subject: [PATCH 24/32] wip

---
 src/web/app/common/tags/messaging/room.tag    |  35 +++--
 src/web/app/common/tags/signin.tag            |  40 +++--
 src/web/app/common/tags/signup.tag            | 142 +++++++++---------
 src/web/app/common/tags/time.tag              |  57 ++++---
 .../app/desktop/tags/big-follow-button.tag    |  78 ++++++----
 .../desktop/tags/messaging/room-window.tag    |   4 +-
 src/web/app/desktop/tags/messaging/window.tag |   7 +-
 7 files changed, 203 insertions(+), 160 deletions(-)

diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index 8b1220e29..cb676badb 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -176,7 +176,7 @@
 				this.connection.socket.send(JSON.stringify({
 					type: 'read',
 					id: message.id
-				});
+				}));
 			}
 			this.update();
 
@@ -197,7 +197,7 @@
 					this.messages[exist].is_read = true;
 					this.update();
 				}
-			}):
+			});
 		};
 
 		this.isBottom = () => {
@@ -206,7 +206,7 @@
 			return current > (max - 32);
 		};
 
-		this.scroll-to-bottom = () => {
+		this.scrollToBottom = () => {
 			this.root.scrollTop = this.root.scrollHeight;
 		};
 
@@ -215,23 +215,26 @@
 			n.innerHTML = '<i class="fa fa-arrow-circle-down"></i>' + message;
 			n.onclick = () => {
 				this.scrollToBottom();
-				n.parentNode.removeChild n
-			this.refs.notifications.appendChild n
+				n.parentNode.removeChild(n);
+			};
+			this.refs.notifications.appendChild(n);
 
-			setTimeout =>
-				n.style.opacity = 0
-				setTimeout =>
-					n.parentNode.removeChild n
-				, 1000ms
-			, 4000ms
+			setTimeout(() => {
+				n.style.opacity = 0;
+				setTimeout(() => n.parentNode.removeChild(n), 1000);
+			}, 4000);
 		};
 
 		this.onVisibilitychange = () => {
-			if document.hidden then return
-			@messages.forEach (message) =>
-				if message.user_id != this.I.id and not message.is_read
-					@connection.socket.send JSON.stringify do
-						type: 'read' 
+			if (document.hidden) return;
+			this.messages.forEach(message => {
+				if (message.user_id !== this.I.id && !message.is_read) {
+					this.connection.socket.send(JSON.stringify({
+						type: 'read',
 						id: message.id
+					}));
+				}
+			});
+		};
 	</script>
 </mk-messaging-room>
diff --git a/src/web/app/common/tags/signin.tag b/src/web/app/common/tags/signin.tag
index e2b873682..c44ae3d6e 100644
--- a/src/web/app/common/tags/signin.tag
+++ b/src/web/app/common/tags/signin.tag
@@ -105,34 +105,42 @@
 		this.oninput = () => {
 			this.api('users/show', {
 				username: this.refs.username.value
-			}).then((user) => {
-				this.user = user
-				this.trigger 'user' user
+			}).then(user => {
+				this.user = user;
+				this.trigger('user', user);
 				this.update();
+			});
+		};
 
-		this.onsubmit = (e) => {
+		this.onsubmit = e => {
 			e.preventDefault();
 
-			if this.refs.username.value == ''
+			if (this.refs.username.value == '') {
 				this.refs.username.focus();
-				return false
-			if this.refs.password.value == ''
+				return false;
+			}
+			if (this.refs.password.value == '') {
 				this.refs.password.focus();
-				return false
+				return false;
+			}
 
-			this.signing = true
-			this.update();
+			this.update({
+				signing: true
+			});
 
 			this.api('signin', {
-				username: this.refs.username.value
+				username: this.refs.username.value,
 				password: this.refs.password.value
 			}).then(() => {
 				location.reload();
-			.catch =>
-				alert 'something happened'
-				this.signing = false
-				this.update();
+			}).catch(() => {
+				alert('something happened');
+				this.update({
+					signing: false
+				});
+			});
 
-			false
+			return false;
+		};
 	</script>
 </mk-signin>
diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag
index 39d4522e7..dafdf51e1 100644
--- a/src/web/app/common/tags/signup.tag
+++ b/src/web/app/common/tags/signup.tag
@@ -185,112 +185,114 @@
 		window.onEecaptchaed = () => {
 			this.recaptchaed = true;
 			this.update();
-		}
+		};
 
 		window.onRecaptchaExpired = () => {
 			this.recaptchaed = false;
 			this.update();
-		}
+		};
 
 		this.on('mount', () => {
-			const head = (document.getElementsByTagName('head'))[0];
-			script = document.createElement 'script' 
-				..setAttribute 'src' \https://www.google.com/recaptcha/api.js
-			head.appendChild script
+			const head = document.getElementsByTagName('head')[0];
+			const script = document.createElement('script');
+			script.setAttribute('src', 'https://www.google.com/recaptcha/api.js');
+			head.appendChild(script);
 		});
 
-		this.on-change-username = () => {
-			username = this.refs.username.value
+		this.onChangeUsername = () => {
+			const username = this.refs.username.value;
 
-			if username == ''
-				this.username-state = null
-				this.update();
-				return
+			if (username == '') {
+				this.update({
+					usernameState: null
+				});
+				return;
+			}
 
-			err = switch
-				| not username.match /^[a-zA-Z0-9\-]+$/ => 'invalid-format' 
-				| username.length < 3chars              => 'min-range' 
-				| username.length > 20chars             => 'max-range' 
-				| _                                     => null
+			const err =
+				!username.match(/^[a-zA-Z0-9\-]+$/) ? 'invalid-format' :
+				username.length < 3 ? 'min-range' :
+				username.length > 20 ? 'max-range' :
+				null;
 
-			if err?
-				this.username-state = err
-				this.update();
-			else
-				this.username-state = 'wait' 
-				this.update();
+			if (err) {
+				this.update({
+					usernameState: err
+				});
+				return;
+			}
 
-				this.api('username/available', {
-					username: username
-				}).then((result) => {
-					if result.available
-						this.username-state = 'ok' 
-					else
-						this.username-state = 'unavailable' 
-					this.update();
-				.catch (err) =>
-					this.username-state = 'error' 
-					this.update();
+			this.update({
+				usernameState: 'wait'
+			});
 
-		this.on-change-password = () => {
-			password = this.refs.password.value
+			this.api('username/available', {
+				username: username
+			}).then(result => {
+				this.update({
+					usernameState: result.available ? 'ok' : 'unavailable'
+				});
+			}).catch(err => {
+				this.update({
+					usernameState: 'error'
+				});
+			});
+		};
 
-			if password == ''
-				this.password-strength = ''
-				return
+		this.onChangePassword = () => {
+			const password = this.refs.password.value;
 
-			strength = @get-password-strength password
+			if (password == '') {
+				this.passwordStrength = '';
+				return;
+			}
 
-			if strength > 0.3
-				this.password-strength = 'medium' 
-				if strength > 0.7
-					this.password-strength = 'high' 
-			else
-				this.password-strength = 'low' 
+			const strength = this.getPasswordStrength(password);
+			this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low';
+			this.refs.passwordMetar.style.width = `${strength * 100}%`;
+		};
 
-			this.update();
+		this.onChangePasswordRetype = () => {
+			const password = this.refs.password.value;
+			const retypedPassword = this.refs.passwordRetype.value;
 
-			this.refs.password-metar.style.width = (strength * 100) + '%' 
+			if (retyped-password == '') {
+				this.passwordRetypeState = null;
+				return;
+			}
 
-		this.on-change-password-retype = () => {
-			password = this.refs.password.value
-			retyped-password = this.refs.password-retype.value
+			this.passwordRetypeState = password == retypedPassword ? 'match' : 'not-match';
+		};
 
-			if retyped-password == ''
-				this.password-retype-state = null
-				return
-
-			if password == retyped-password
-				this.password-retype-state = 'match' 
-			else
-				this.password-retype-state = 'not-match' 
-
-		this.onsubmit = (e) => {
+		this.onsubmit = e => {
 			e.preventDefault();
 
 			const username = this.refs.username.value;
 			const password = this.refs.password.value;
 
-			locker = document.body.appendChild(document.createElement('mk-locker'));
- 
+			const locker = document.body.appendChild(document.createElement('mk-locker'));
+
 			this.api('signup', {
 				username: username,
 				password: password,
 				'g-recaptcha-response': grecaptcha.getResponse()
 			}).then(() => {
 				this.api('signin', {
-					username: username
+					username: username,
 					password: password
 				}).then(() => {
 					location.href = CONFIG.url
-			.catch =>
-				alert '何らかの原因によりアカウントの作成に失敗しました。再度お試しください。'
+				});
+			}).catch(() => {
+				alert('何らかの原因によりアカウントの作成に失敗しました。再度お試しください。');
 
-				grecaptcha.reset!
-				this.recaptchaed = false
+				grecaptcha.reset();
+				this.recaptchaed = false;
 
-				locker.parentNode.removeChild locker
+				locker.parentNode.removeChild(locker);
+			});
 
-			false
+			return false;
+		};
 	</script>
 </mk-signup>
diff --git a/src/web/app/common/tags/time.tag b/src/web/app/common/tags/time.tag
index 1bf078916..ad34115f6 100644
--- a/src/web/app/common/tags/time.tag
+++ b/src/web/app/common/tags/time.tag
@@ -1,41 +1,50 @@
 <mk-time>
-	<time datetime={ opts.time }><span if={ mode == 'relative' }>{ relative }</span><span if={ mode == 'absolute' }>{ absolute }</span><span if={ mode == 'detail' }>{ absolute } ({ relative })</span></time>
+	<time datetime={ opts.time }>
+		<span if={ mode == 'relative' }>{ relative }</span>
+		<span if={ mode == 'absolute' }>{ absolute }</span>
+		<span if={ mode == 'detail' }>{ absolute } ({ relative })</span>
+	</time>
 	<script>
-		this.time = new Date this.opts.time
-		this.mode = this.opts.mode || 'relative' 
-		this.tickid = null
+		this.time = new Date(this.opts.time);
+		this.mode = this.opts.mode || 'relative';
+		this.tickid = null;
 
-		this.absolute = 
-			this.time.getFullYear() + '年' +
+		this.absolute =
+			this.time.getFullYear()  + '年' +
 			this.time.getMonth() + 1 + '月' +
 			this.time.getDate()      + '日' +
 			' ' +
 			this.time.getHours()     + '時' +
-			this.time.getMinutes()   + '分' 
+			this.time.getMinutes()   + '分';
 
 		this.on('mount', () => {
-			if this.mode == 'relative' or this.mode == 'detail' 
-				this.tick!
-				this.tickid = setInterval this.tick, 1000ms
+			if (this.mode == 'relative' || this.mode == 'detail') {
+				this.tick();
+				this.tickid = setInterval(this.tick, 1000);
+			}
+		});
 
 		this.on('unmount', () => {
-			if this.mode == 'relative' or this.mode == 'detail' 
-				clearInterval this.tickid
+			if (this.mode === 'relative' || this.mode === 'detail') {
+				clearInterval(this.tickid);
+			}
+		});
 
 		this.tick = () => {
 			const now = new Date();
-			ago = (now - this.time) / 1000ms
-			this.relative = switch
-				| ago >= 31536000s => ~~(ago / 31536000s) + '年前'
-				| ago >= 2592000s  => ~~(ago / 2592000s)  + 'ヶ月前'
-				| ago >= 604800s   => ~~(ago / 604800s)   + '週間前'
-				| ago >= 86400s    => ~~(ago / 86400s)    + '日前'
-				| ago >= 3600s     => ~~(ago / 3600s)     + '時間前'
-				| ago >= 60s       => ~~(ago / 60s)       + '分前'
-				| ago >= 10s       => ~~(ago % 60s)       + '秒前'
-				| ago >= 0s        =>                       'たった今'
-				| ago <  0s        =>                       '未来'
-				| _                =>                       'なぞのじかん'
+			const ago = (now - this.time) / 1000/*ms*/;
+			this.relative =
+				ago >= 31536000 ? ~~(ago / 31536000) + '年前' :
+				ago >= 2592000  ? ~~(ago / 2592000)  + 'ヶ月前' :
+				ago >= 604800   ? ~~(ago / 604800)   + '週間前' :
+				ago >= 86400    ? ~~(ago / 86400)    + '日前' :
+				ago >= 3600     ? ~~(ago / 3600)     + '時間前' :
+				ago >= 60       ? ~~(ago / 60)       + '分前' :
+				ago >= 10       ? ~~(ago % 60)       + '秒前' :
+				ago >= 0        ?                      'たった今' :
+				ago <  0        ?                      '未来' :
+				                                       'なぞのじかん';
 			this.update();
+		};
 	</script>
 </mk-time>
diff --git a/src/web/app/desktop/tags/big-follow-button.tag b/src/web/app/desktop/tags/big-follow-button.tag
index 309e6ce8e..9d12b5a53 100644
--- a/src/web/app/desktop/tags/big-follow-button.tag
+++ b/src/web/app/desktop/tags/big-follow-button.tag
@@ -74,54 +74,70 @@
 		this.mixin('is-promise');
 		this.mixin('stream');
 
-		this.user = null
-		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
-		this.init = true
-		this.wait = false
+		this.user = null;
+		this.userPromise = this.isPromise(this.opts.user)
+			? this.opts.user
+			: Promise.resolve(this.opts.user);
+		this.init = true;
+		this.wait = false;
 
 		this.on('mount', () => {
-			this.user-promise}).then((user) => {
-				this.user = user
-				this.init = false
-				this.update();
-				this.stream.on 'follow' this.on-stream-follow
-				this.stream.on 'unfollow' this.on-stream-unfollow
+			this.userPromise.then(user => {
+				this.update({
+					init: false,
+					user: user
+				});
+				this.stream.on('follow', this.onStreamFollow);
+				this.stream.on('unfollow', this.onStreamUnfollow);
+			});
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'follow' this.on-stream-follow
-			this.stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off('follow', this.onStreamFollow);
+			this.stream.off('unfollow', this.onStreamUnfollow);
+		});
 
-		this.on-stream-follow = (user) => {
-			if user.id == this.user.id
-				this.user = user
-				this.update();
+		this.onStreamFollow = user => {
+			if (user.id == this.user.id) {
+				this.update({
+					user: user
+				});
+			}
+		};
 
-		this.on-stream-unfollow = (user) => {
-			if user.id == this.user.id
-				this.user = user
-				this.update();
+		this.onStreamUnfollow = user => {
+			if (user.id == this.user.id) {
+				this.update({
+					user: user
+				});
+			}
+		};
 
 		this.onclick = () => {
-			this.wait = true
-			if this.user.is_following
+			this.wait = true;
+			if (this.user.is_following) {
 				this.api('following/delete', {
 					user_id: this.user.id
 				}).then(() => {
-					this.user.is_following = false
-				.catch (err) ->
-					console.error err
+					this.user.is_following = false;
+				}).catch(err => {
+					console.error(err);
 				}).then(() => {
-					this.wait = false
+					this.wait = false;
 					this.update();
-			else
+				});
+			} else {
 				this.api('following/create', {
 					user_id: this.user.id
 				}).then(() => {
-					this.user.is_following = true
-				.catch (err) ->
-					console.error err
+					this.user.is_following = true;
+				}).catch(err => {
+					console.error(err);
 				}).then(() => {
-					this.wait = false
+					this.wait = false;
 					this.update();
+				});
+			}
+		};
 	</script>
 </mk-big-follow-button>
diff --git a/src/web/app/desktop/tags/messaging/room-window.tag b/src/web/app/desktop/tags/messaging/room-window.tag
index 3cf10ffe1..e8a9ed6ac 100644
--- a/src/web/app/desktop/tags/messaging/room-window.tag
+++ b/src/web/app/desktop/tags/messaging/room-window.tag
@@ -19,10 +19,12 @@
 
 	</style>
 	<script>
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.on('mount', () => {
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
+		});
 	</script>
 </mk-messaging-room-window>
diff --git a/src/web/app/desktop/tags/messaging/window.tag b/src/web/app/desktop/tags/messaging/window.tag
index 208404d15..c7af1dc2a 100644
--- a/src/web/app/desktop/tags/messaging/window.tag
+++ b/src/web/app/desktop/tags/messaging/window.tag
@@ -22,10 +22,13 @@
 		this.on('mount', () => {
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
 
 			this.refs.window.refs.index.on('navigate-user', user => {
-				w = document.body.appendChild(document.createElement('mk-messaging-room-window'));
- 				riot.mount w, do
+				riot.mount(document.body.appendChild(document.createElement('mk-messaging-room-window')), {
 					user: user
+				});
+			});
+		});
 	</script>
 </mk-messaging-window>

From 8647c1d71c833691362e9e1b29683773f1558dc0 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 20:05:03 +0900
Subject: [PATCH 25/32] wip

---
 src/web/app/common/tags/messaging/index.tag   | 79 +++++++++++--------
 src/web/app/desktop/tags/pages/entrance.tag   | 20 +++--
 .../desktop/tags/pages/entrance/signin.tag    | 10 ++-
 .../desktop/tags/pages/entrance/signup.tag    |  4 -
 src/web/app/desktop/tags/pages/home.tag       | 42 +++++-----
 src/web/app/desktop/tags/pages/not-found.tag  | 45 +----------
 src/web/app/desktop/tags/pages/post.tag       |  5 +-
 src/web/app/desktop/tags/pages/search.tag     |  3 +-
 src/web/app/desktop/tags/pages/user.tag       |  8 +-
 src/web/app/desktop/tags/search-posts.tag     | 77 +++++++++---------
 src/web/app/desktop/tags/search.tag           |  4 +-
 src/web/app/desktop/tags/user-photos.tag      | 40 ++++++----
 src/web/app/desktop/tags/user-posts-graph.tag | 71 -----------------
 src/web/app/desktop/tags/user-preview.tag     | 57 ++++++-------
 14 files changed, 198 insertions(+), 267 deletions(-)
 delete mode 100644 src/web/app/desktop/tags/user-posts-graph.tag

diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
index 6ba6cb7d9..2dbf76bd9 100644
--- a/src/web/app/common/tags/messaging/index.tag
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -309,49 +309,64 @@
 			const q = this.refs.search.value;
 			if (q == '') {
 				this.searchResult = [];
-			} else {
-				this.api('users/search', {
-					query: q
-					max: 5
-				}).then((users) => {
-					users.forEach (user) =>
-						user._click = =>
-							this.trigger 'navigate-user' user
-							this.searchResult = []
-					this.searchResult = users
-					this.update();
-				.catch (err) =>
-					console.error err
+				return;
+			}
+			this.api('users/search', {
+				query: q,
+				max: 5
+			}).then(users => {
+				users.forEach(user => {
+					user._click = () => {
+						this.trigger('navigate-user', user);
+						this.searchResult = [];
+					};
+				});
+				this.update({
+					searchResult: users
+				});
+			});
 		};
 
-		this.on-search-keydown = e => {
-			const key = e.which;
-			switch (key)
-				| 9, 40 => // Key[TAB] or Key[↓]
+		this.onSearchKeydown = e => {
+			switch (e.which) {
+				case 9: // [TAB]
+				case 40: // [↓]
 					e.preventDefault();
 					e.stopPropagation();
 					this.refs.searchResult.childNodes[0].focus();
+					break;
+			}
 		};
 
-		this.on-searchResult-keydown = (i, e) => {
-			key = e.which
-			switch (key)
-				| 10, 13 => // Key[ENTER]
-					e.preventDefault();
-					e.stopPropagation();
+		this.onSearchResultKeydown = (i, e) => {
+			const cancel = () => {
+				e.preventDefault();
+				e.stopPropagation();
+			};
+			switch (true) {
+				case e.which == 10: // [ENTER]
+				case e.which == 13: // [ENTER]
+					cancel();
 					this.searchResult[i]._click();
-				| 27 => // Key[ESC]
-					e.preventDefault();
-					e.stopPropagation();
+					break;
+
+				case e.which == 27: // [ESC]
+					cancel();
 					this.refs.search.focus();
-				| 38 => // Key[↑]
-					e.preventDefault();
-					e.stopPropagation();
+					break;
+
+				case e.which == 9 && e.shiftKey: // [TAB] + [Shift]
+				case e.which == 38: // [↑]
+					cancel();
 					(this.refs.searchResult.childNodes[i].previousElementSibling || this.refs.searchResult.childNodes[this.searchResult.length - 1]).focus();
-				| 9, 40 => // Key[TAB] or Key[↓]
-					e.preventDefault();
-					e.stopPropagation();
+					break;
+
+				case e.which == 9: // [TAB]
+				case e.which == 40: // [↓]
+					cancel();
 					(this.refs.searchResult.childNodes[i].nextElementSibling || this.refs.searchResult.childNodes[0]).focus();
+					break;
+			}
 		};
 
 	</script>
diff --git a/src/web/app/desktop/tags/pages/entrance.tag b/src/web/app/desktop/tags/pages/entrance.tag
index 486f83f9d..82ac8539c 100644
--- a/src/web/app/desktop/tags/pages/entrance.tag
+++ b/src/web/app/desktop/tags/pages/entrance.tag
@@ -63,18 +63,24 @@
 
 	</style>
 	<script>
-		this.mode = 'signin' 
+		this.mode = 'signin';
 
 		this.signup = () => {
-			this.mode = 'signup' 
-			this.update();
+			this.update({
+				mode: 'signup'
+			});
+		};
 
 		this.signin = () => {
-			this.mode = 'signin' 
-			this.update();
+			this.update({
+				mode: 'signin'
+			});
+		};
 
 		this.introduction = () => {
-			this.mode = 'introduction' 
-			this.update();
+			this.update({
+				mode: 'introduction'
+			});
+		};
 	</script>
 </mk-entrance>
diff --git a/src/web/app/desktop/tags/pages/entrance/signin.tag b/src/web/app/desktop/tags/pages/entrance/signin.tag
index b620c88b8..bd4b47c7d 100644
--- a/src/web/app/desktop/tags/pages/entrance/signin.tag
+++ b/src/web/app/desktop/tags/pages/entrance/signin.tag
@@ -120,11 +120,15 @@
 	</style>
 	<script>
 		this.on('mount', () => {
-			this.refs.signin.on('user', (user) => {
-				@update do
+			this.refs.signin.on('user', user => {
+				this.update({
 					user: user
+				});
+			});
+		});
 
 		this.introduction = () => {
-			this.parent.introduction!
+			this.parent.introduction();
+		};
 	</script>
 </mk-entrance-signin>
diff --git a/src/web/app/desktop/tags/pages/entrance/signup.tag b/src/web/app/desktop/tags/pages/entrance/signup.tag
index 1a777fe96..7ab53759c 100644
--- a/src/web/app/desktop/tags/pages/entrance/signup.tag
+++ b/src/web/app/desktop/tags/pages/entrance/signup.tag
@@ -43,9 +43,5 @@
 				> i
 					padding 14px
 
-			
-
-			
-
 	</style>
 </mk-entrance-signup>
diff --git a/src/web/app/desktop/tags/pages/home.tag b/src/web/app/desktop/tags/pages/home.tag
index 433137e9c..e988cbc76 100644
--- a/src/web/app/desktop/tags/pages/home.tag
+++ b/src/web/app/desktop/tags/pages/home.tag
@@ -5,7 +5,6 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('i');
@@ -14,34 +13,37 @@
 		this.mixin('stream');
 		this.mixin('get-post-summary');
 
-		this.unread-count = 0
+		this.unreadCount = 0;
 
-		this.page = switch this.opts.mode
-			| 'timelie' => 'home' 
-			| 'mentions' => 'mentions' 
-			| _ => 'home' 
+		this.page = this.opts.mode || 'timeline';
 
 		this.on('mount', () => {
 			this.refs.ui.refs.home.on('loaded', () => {
 				this.Progress.done();
-
-			document.title = 'Misskey'
+			});
+			document.title = 'Misskey';
 			this.Progress.start();
-			this.stream.on 'post' this.on-stream-post
-			document.addEventListener 'visibilitychange' @window-onVisibilitychange, false
+			this.stream.on('post', this.onStreamPost);
+			document.addEventListener('visibilitychange', this.windowOnVisibilitychange, false);
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'post' this.on-stream-post
-			document.removeEventListener 'visibilitychange' @window-onVisibilitychange
+			this.stream.off('post', this.onStreamPost);
+			document.removeEventListener('visibilitychange', this.windowOnVisibilitychange);
+		});
 
-		this.on-stream-post = (post) => {
-			if document.hidden and post.user_id !== this.I.id
-				@unread-count++
-				document.title = '(' + @unread-count + ') ' + @get-post-summary post
+		this.onStreamPost = post => {
+			if (document.hidden && post.user_id != this.I.id) {
+				this.unreadCount++;
+				document.title = `(${this.unreadCount}) ${this.getPostSummary(post)}`;
+			}
+		};
 
-		this.window-onVisibilitychange = () => {
-			if !document.hidden
-				this.unread-count = 0
-				document.title = 'Misskey'
+		this.windowOnVisibilitychange = () => {
+			if (!document.hidden) {
+				this.unreadCount = 0;
+				document.title = 'Misskey';
+			}
+		};
 	</script>
 </mk-home-page>
diff --git a/src/web/app/desktop/tags/pages/not-found.tag b/src/web/app/desktop/tags/pages/not-found.tag
index a7cbad0b8..e62ea1100 100644
--- a/src/web/app/desktop/tags/pages/not-found.tag
+++ b/src/web/app/desktop/tags/pages/not-found.tag
@@ -1,54 +1,11 @@
 <mk-not-found>
 	<mk-ui>
 		<main>
-			<h1>Not Found</h1><img src="/_/resources/rogge.jpg" alt=""/>
-			<div class="mask"></div>
+			<h1>Not Found</h1>
 		</main>
 	</mk-ui>
 	<style>
 		:scope
 			display block
-
-			main
-				display block
-				width 600px
-				margin 32px auto
-
-				> img
-					display block
-					width 600px
-					height 459px
-					pointer-events none
-					user-select none
-					border-radius 16px
-					box-shadow 0 0 16px rgba(0, 0, 0, 0.1)
-
-				> h1
-					display block
-					margin 0
-					padding 0
-					position absolute
-					top 260px
-					left 225px
-					transform rotate(-12deg)
-					z-index 2
-					color #444
-					font-size 24px
-					line-height 20px
-
-				> .mask
-					position absolute
-					top 262px
-					left 217px
-					width 126px
-					height 18px
-					transform rotate(-12deg)
-					background #D6D5DA
-					border-radius 2px 6px 7px 6px
-
-			
-
-			
-
 	</style>
 </mk-not-found>
diff --git a/src/web/app/desktop/tags/pages/post.tag b/src/web/app/desktop/tags/pages/post.tag
index c3298b890..b04ba69dc 100644
--- a/src/web/app/desktop/tags/pages/post.tag
+++ b/src/web/app/desktop/tags/pages/post.tag
@@ -18,15 +18,18 @@
 	<script>
 		this.mixin('ui-progress');
 
-		this.post = this.opts.post
+		this.post = this.opts.post;
 
 		this.on('mount', () => {
 			this.Progress.start();
 
 			this.refs.ui.refs.detail.on('post-fetched', () => {
 				this.Progress.set(0.5);
+			});
 
 			this.refs.ui.refs.detail.on('loaded', () => {
 				this.Progress.done();
+			});
+		});
 	</script>
 </mk-post-page>
diff --git a/src/web/app/desktop/tags/pages/search.tag b/src/web/app/desktop/tags/pages/search.tag
index fa0ebee0a..ace9e27ab 100644
--- a/src/web/app/desktop/tags/pages/search.tag
+++ b/src/web/app/desktop/tags/pages/search.tag
@@ -5,7 +5,6 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('ui-progress');
@@ -15,5 +14,7 @@
 
 			this.refs.ui.refs.search.on('loaded', () => {
 				this.Progress.done();
+			});
+		});
 	</script>
 </mk-search-page>
diff --git a/src/web/app/desktop/tags/pages/user.tag b/src/web/app/desktop/tags/pages/user.tag
index 3bbfbe859..767af31e9 100644
--- a/src/web/app/desktop/tags/pages/user.tag
+++ b/src/web/app/desktop/tags/pages/user.tag
@@ -5,21 +5,23 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('ui-progress');
 
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.on('mount', () => {
 			this.Progress.start();
 
-			this.refs.ui.refs.user.on('user-fetched', (user) => {
+			this.refs.ui.refs.user.on('user-fetched', user => {
 				this.Progress.set(0.5);
 				document.title = user.name + ' | Misskey'
+			});
 
 			this.refs.ui.refs.user.on('loaded', () => {
 				this.Progress.done();
+			});
+		});
 	</script>
 </mk-user-page>
diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag
index 248b8cc87..95ee33a5a 100644
--- a/src/web/app/desktop/tags/search-posts.tag
+++ b/src/web/app/desktop/tags/search-posts.tag
@@ -31,56 +31,61 @@
 		this.mixin('api');
 		this.mixin('get-post-summary');
 
-		this.query = this.opts.query
-		this.is-loading = true
-		this.is-empty = false
-		this.more-loading = false
-		this.page = 0
+		this.query = this.opts.query;
+		this.isLoading = true;
+		this.isEmpty = false;
+		this.moreLoading = false;
+		this.page = 0;
 
 		this.on('mount', () => {
-			document.addEventListener 'keydown' this.on-document-keydown
-			window.addEventListener 'scroll' this.on-scroll
+			document.addEventListener('keydown', this.onDocumentKeydown);
+			window.addEventListener('scroll', this.onScroll);
 
 			this.api('posts/search', {
 				query: this.query
-			}).then((posts) => {
-				this.is-loading = false
-				this.is-empty = posts.length == 0
-				this.update();
-				this.refs.timeline.set-posts posts
+			}).then(posts => {
+				this.update({
+					isLoading: false,
+					isEmpty: posts.length == 0
+				});
+				this.refs.timeline.setPosts(posts);
 				this.trigger('loaded');
-			.catch (err) =>
-				console.error err
+			});
+		});
 
 		this.on('unmount', () => {
-			document.removeEventListener 'keydown' this.on-document-keydown
-			window.removeEventListener 'scroll' this.on-scroll
+			document.removeEventListener('keydown', this.onDocumentKeydown);
+			window.removeEventListener('scroll', this.onScroll);
+		});
 
-		this.on-document-keydown = (e) => {
-			tag = e.target.tag-name.to-lower-case!
-			if tag != 'input' and tag != 'textarea' 
-				if e.which == 84 // t
+		this.onDocumentKeydown = e => {
+			if (e.target.tagName != 'INPUT' && e.target.tagName != 'TEXTAREA') {
+				if (e.which == 84) { // t
 					this.refs.timeline.focus();
+				}
+			}
+		};
 
 		this.more = () => {
-			if @more-loading or @is-loading or this.timeline.posts.length == 0
-				return
-			this.more-loading = true
-			this.update();
+			if (this.moreLoading || this.isLoading || this.timeline.posts.length == 0) return;
+			this.update({
+				moreLoading: true
+			});
 			this.api('posts/search', {
-				query: this.query
+				query: this.query,
 				page: this.page + 1
-			}).then((posts) => {
-				this.more-loading = false
-				this.page++
-				this.update();
-				this.refs.timeline.prepend-posts posts
-			.catch (err) =>
-				console.error err
+			}).then(posts => {
+				this.update({
+					moreLoading: false,
+					page: page + 1
+				});
+				this.refs.timeline.prependPosts(posts);
+			});
+		};
 
-		this.on-scroll = () => {
-			current = window.scrollY + window.inner-height
-			if current > document.body.offset-height - 16 // 遊び
-				@more!
+		this.onScroll = () => {
+			const current = window.scrollY + window.innerHeight;
+			if (current > document.body.offsetHeight - 16) this.more();
+		};
 	</script>
 </mk-search-posts>
diff --git a/src/web/app/desktop/tags/search.tag b/src/web/app/desktop/tags/search.tag
index 82a1d7986..681b4c8ae 100644
--- a/src/web/app/desktop/tags/search.tag
+++ b/src/web/app/desktop/tags/search.tag
@@ -23,10 +23,12 @@
 
 	</style>
 	<script>
-		this.query = this.opts.query
+		this.query = this.opts.query;
 
 		this.on('mount', () => {
 			this.refs.posts.on('loaded', () => {
 				this.trigger('loaded');
+			});
+		});
 	</script>
 </mk-search>
diff --git a/src/web/app/desktop/tags/user-photos.tag b/src/web/app/desktop/tags/user-photos.tag
index 9cde9b8c4..a72b1f302 100644
--- a/src/web/app/desktop/tags/user-photos.tag
+++ b/src/web/app/desktop/tags/user-photos.tag
@@ -60,27 +60,33 @@
 		this.mixin('api');
 		this.mixin('is-promise');
 
-		this.images = []
-		this.initializing = true
-
-		this.user = null
-		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
+		this.images = [];
+		this.initializing = true;
+		this.user = null;
+		this.userPromise = this.isPromise(this.opts.user)
+			? this.opts.user
+			: Promise.resolve(this.opts.user);
 
 		this.on('mount', () => {
-			this.user-promise}).then((user) => {
-				this.user = user
-				this.update();
+			this.userPromise.then(user => {
+				this.update({
+					user: user
+				});
 
 				this.api('users/posts', {
-					user_id: this.user.id
-					with_media: true
-					limit: 9posts
-				}).then((posts) => {
-					this.initializing = false
-					posts.forEach (post) =>
-						post.media.forEach (image) =>
-							if @images.length < 9
-								@images.push image
+					user_id: this.user.id,
+					with_media: true,
+					limit: 9
+				}).then(posts => {
+					this.initializing = false;
+					posts.forEach(post => {
+						post.media.forEach(media => {
+							if (this.images.length < 9) this.images.push(image);
+						});
+					});
 					this.update();
+				});
+			});
+		});
 	</script>
 </mk-user-photos>
diff --git a/src/web/app/desktop/tags/user-posts-graph.tag b/src/web/app/desktop/tags/user-posts-graph.tag
deleted file mode 100644
index d1760c6b3..000000000
--- a/src/web/app/desktop/tags/user-posts-graph.tag
+++ /dev/null
@@ -1,71 +0,0 @@
-<mk-user-posts-graph>
-	<canvas ref="canv" width="750" height="250"></canvas>
-	<style>
-		:scope
-			display block
-			width 750px
-			height 250px
-
-	</style>
-	<script>
-		this.mixin('api');
-		this.mixin('is-promise');
-
-		this.user = null
-		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
-
-		this.on('mount', () => {
-			user <~ this.user-promise.then
-			this.user = user
-			this.update();
-
-			this.api('aggregation/users/post', {
-				user_id: this.user.id
-				limit: 30days
-			}).then((data) => {
-				data = data.reverse!
-				new Chart this.refs.canv, do
-					type: 'line' 
-					data:
-						labels: data.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
-						datasets: [
-							{
-								label: '投稿' 
-								data: data.map (x) => x.posts
-								line-tension: 0
-								point-radius: 0
-								background-color: '#555' 
-								border-color: 'transparent' 
-							},
-							{
-								label: 'Repost' 
-								data: data.map (x) => x.reposts
-								line-tension: 0
-								point-radius: 0
-								background-color: '#a2d61e' 
-								border-color: 'transparent' 
-							},
-							{
-								label: '返信' 
-								data: data.map (x) => x.replies
-								line-tension: 0
-								point-radius: 0
-								background-color: '#F7796C' 
-								border-color: 'transparent' 
-							}
-						]
-					options:
-						responsive: false
-						scales:
-							x-axes: [
-								{
-									stacked: true
-								}
-							]
-							y-axes: [
-								{
-									stacked: true
-								}
-							]
-	</script>
-</mk-user-posts-graph>
diff --git a/src/web/app/desktop/tags/user-preview.tag b/src/web/app/desktop/tags/user-preview.tag
index 8dd6551c4..f9806534e 100644
--- a/src/web/app/desktop/tags/user-preview.tag
+++ b/src/web/app/desktop/tags/user-preview.tag
@@ -100,44 +100,47 @@
 		this.mixin('i');
 		this.mixin('api');
 
-		this.u = this.opts.user
-		this.user = null
-		this.user-promise = 
-			if typeof @u == 'string' 
-				new Promise (resolve, reject) =>
+		this.u = this.opts.user;
+		this.user = null;
+		this.userPromise =
+			typeof this.u == 'string' ?
+				new Promise((resolve, reject) => {
 					this.api('users/show', {
-						user_id: if @u.0 == '@' then undefined else @u
-						username: if @u.0 == '@' then @u.substr 1 else undefined
-					}).then((user) => {
-						resolve user
-			else
-				Promise.resolve @u
+						user_id: this.u[0] == '@' ? undefined : this.u,
+						username: this.u[0] == '@' ? this.u.substr(1) : undefined
+					}).then(resolve);
+				})
+			: Promise.resolve(this.u);
 
 		this.on('mount', () => {
-			this.user-promise}).then((user) => {
-				this.user = user
-				this.update();
+			this.userPromise.then(user => {
+				this.update({
+					user: user
+				});
+			});
 
 			Velocity(this.root, {
-				opacity: 0
-				'margin-top': '-8px' 
-			} 0ms
+				opacity: 0,
+				'margin-top': '-8px'
+			}, 0);
 			Velocity(this.root, {
-				opacity: 1
+				opacity: 1,
 				'margin-top': 0
 			}, {
-				duration: 200ms
-				easing: 'ease-out' 
-			}
+				duration: 200,
+				easing: 'ease-out'
+			});
+		});
 
 		this.close = () => {
 			Velocity(this.root, {
-				opacity: 0
-				'margin-top': '-8px' 
+				opacity: 0,
+				'margin-top': '-8px'
 			}, {
-				duration: 200ms
-				easing: 'ease-out' 
-				complete: => this.unmount();
-			}
+				duration: 200,
+				easing: 'ease-out',
+				complete: () => this.unmount()
+			});
+		};
 	</script>
 </mk-user-preview>

From 2de118a45d0c9da11f652f9603650bd4008d8d4d Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 20:34:54 +0900
Subject: [PATCH 26/32] wip

---
 src/web/app/common/tags/signin-history.tag    |  24 ++--
 .../app/desktop/tags/following-setuper.tag    |  58 ++++----
 src/web/app/desktop/tags/image-dialog.tag     |  35 ++---
 src/web/app/desktop/tags/images-viewer.tag    |  26 ++--
 src/web/app/desktop/tags/notifications.tag    |  40 +++---
 src/web/app/desktop/tags/post-detail-sub.tag  |  33 +++--
 src/web/app/desktop/tags/post-detail.tag      | 126 ++++++++++--------
 src/web/app/desktop/tags/post-form-window.tag |  23 ++--
 src/web/app/desktop/tags/post-preview.tag     |   4 +-
 src/web/app/desktop/tags/progress-dialog.tag  |  19 ++-
 .../app/desktop/tags/repost-form-window.tag   |  19 ++-
 src/web/app/desktop/tags/repost-form.tag      |  29 ++--
 src/web/app/desktop/tags/ui.tag               |   1 +
 .../app/desktop/tags/user-friends-graph.tag   |  67 ----------
 src/web/app/desktop/tags/user-likes-graph.tag |  42 ------
 15 files changed, 243 insertions(+), 303 deletions(-)
 delete mode 100644 src/web/app/desktop/tags/user-friends-graph.tag
 delete mode 100644 src/web/app/desktop/tags/user-likes-graph.tag

diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag
index 47bf68c28..386898005 100644
--- a/src/web/app/common/tags/signin-history.tag
+++ b/src/web/app/common/tags/signin-history.tag
@@ -55,21 +55,23 @@
 		this.fetching = true;
 
 		this.on('mount', () => {
-			this.api 'i/signin_history' 
-			}).then((history) => {
-				this.history = history
-				this.fetching = false
-				this.update();
-			.catch (err) =>
-				console.error err
+			this.api('i/signin_history').then(history => {
+				this.update({
+					fetching: false,
+					history: history
+				});
+			});
 
-			this.stream.on 'signin' this.on-signin
+			this.stream.on('signin', this.onSignin);
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'signin' this.on-signin
+			this.stream.off('signin', this.onSignin);
+		});
 
-		this.on-signin = (signin) => {
-			@history.unshift signin
+		this.onSignin = signin => {
+			this.history.unshift(signin);
 			this.update();
+		};
 	</script>
 </mk-signin-history>
diff --git a/src/web/app/desktop/tags/following-setuper.tag b/src/web/app/desktop/tags/following-setuper.tag
index 03b26b10e..3dc8fb54c 100644
--- a/src/web/app/desktop/tags/following-setuper.tag
+++ b/src/web/app/desktop/tags/following-setuper.tag
@@ -1,6 +1,6 @@
 <mk-following-setuper>
 	<p class="title">気になるユーザーをフォロー:</p>
-	<div class="users" if={ !loading && users.length > 0 }>
+	<div class="users" if={ !fetching && users.length > 0 }>
 		<div class="user" each={ users }><a class="avatar-anchor" href={ CONFIG.url + '/' + username }><img class="avatar" src={ avatar_url + '?thumbnail&size=42' } alt="" data-user-preview={ id }/></a>
 			<div class="body"><a class="name" href={ CONFIG.url + '/' + username } target="_blank" data-user-preview={ id }>{ name }</a>
 				<p class="username">@{ username }</p>
@@ -8,8 +8,8 @@
 			<mk-follow-button user={ this }></mk-follow-button>
 		</div>
 	</div>
-	<p class="empty" if={ !loading && users.length == 0 }>おすすめのユーザーは見つかりませんでした。</p>
-	<p class="loading" if={ loading }><i class="fa fa-spinner fa-pulse fa-fw"></i>読み込んでいます
+	<p class="empty" if={ !fetching && users.length == 0 }>おすすめのユーザーは見つかりませんでした。</p>
+	<p class="fetching" if={ fetching }><i class="fa fa-spinner fa-pulse fa-fw"></i>読み込んでいます
 		<mk-ellipsis></mk-ellipsis>
 	</p><a class="refresh" onclick={ refresh }>もっと見る</a>
 	<button class="close" onclick={ close } title="閉じる"><i class="fa fa-times"></i></button>
@@ -81,7 +81,7 @@
 				text-align center
 				color #aaa
 
-			> .loading
+			> .fetching
 				margin 0
 				padding 16px
 				text-align center
@@ -126,38 +126,46 @@
 		this.mixin('api');
 		this.mixin('user-preview');
 
-		this.users = null
-		this.loading = true
+		this.users = null;
+		this.fetching = true;
 
-		this.limit = 6users
-		this.page = 0
+		this.limit = 6;
+		this.page = 0;
 
 		this.on('mount', () => {
-			this.load();
+			this.fetch();
+		});
 
-		this.load = () => {
-			this.loading = true
-			this.users = null
-			this.update();
+		this.fetch = () => {
+			this.update({
+				fetching: true,
+				users: null
+			});
 
 			this.api('users/recommendation', {
-				limit: @limit
-				offset: @limit * this.page
-			}).then((users) => {
-				this.loading = false
+				limit: this.limit,
+				offset: this.limit * this.page
+			}).then(users => {
+				this.fetching = false
 				this.users = users
-				this.update();
-			.catch (err, text-status) ->
-				console.error err
+				this.update({
+					fetching: false,
+					users: users
+				});
+			});
+		};
 
 		this.refresh = () => {
-			if this.users.length < @limit
-				this.page = 0
-			else
-				this.page++
-			this.load();
+			if (this.users.length < this.limit) {
+				this.page = 0;
+			} else {
+				this.page++;
+			}
+			this.fetch();
+		};
 
 		this.close = () => {
 			this.unmount();
+		};
 	</script>
 </mk-following-setuper>
diff --git a/src/web/app/desktop/tags/image-dialog.tag b/src/web/app/desktop/tags/image-dialog.tag
index a1acd05f6..91245dac9 100644
--- a/src/web/app/desktop/tags/image-dialog.tag
+++ b/src/web/app/desktop/tags/image-dialog.tag
@@ -35,41 +35,26 @@
 
 	</style>
 	<script>
-		this.image = this.opts.image
+		this.image = this.opts.image;
 
 		this.on('mount', () => {
 			Velocity(this.root, {
 				opacity: 1
 			}, {
-				duration: 100ms
-				easing: 'linear' 
-			}
-
-			#Velocity(@img, {
-			// scale: 1
-			// opacity: 1
-			#}, {
-			// duration: 200ms
-			// easing: 'ease-out' 
-			#}
+				duration: 100,
+				easing: 'linear'
+			});
+		});
 
 		this.close = () => {
 			Velocity(this.root, {
 				opacity: 0
 			}, {
-				duration: 100ms
-				easing: 'linear' 
-				complete: => this.unmount();
-			}
+				duration: 100,
+				easing: 'linear',
+				complete: () => this.unmount()
+			});
+		};
 
-			#Velocity(@img, {
-			// scale: 0.9
-			// opacity: 0
-			#}, {
-			// duration: 200ms
-			// easing: 'ease-in' 
-			// complete: =>
-			// 	this.unmount();
-			#}
 	</script>
 </mk-image-dialog>
diff --git a/src/web/app/desktop/tags/images-viewer.tag b/src/web/app/desktop/tags/images-viewer.tag
index e1ceeb0f5..83bce7bf4 100644
--- a/src/web/app/desktop/tags/images-viewer.tag
+++ b/src/web/app/desktop/tags/images-viewer.tag
@@ -26,20 +26,22 @@
 
 	</style>
 	<script>
-		this.images = this.opts.images
-		this.image = @images.0
+		this.images = this.opts.images;
+		this.image = this.images[0];
 
-		this.mousemove = (e) => {
-			rect = this.refs.view.getBoundingClientRect();
-			mouse-x = e.client-x - rect.left
-			mouse-y = e.client-y - rect.top
-			xp = mouse-x / this.refs.view.offset-width * 100
-			yp = mouse-y / this.refs.view.offset-height * 100
-			this.refs.view.style.background-position = xp + '% ' + yp + '%'
+		this.mousemove = e => {
+			const rect = this.refs.view.getBoundingClientRect();
+			const mouseX = e.clientX - rect.left;
+			const mouseY = e.clientY - rect.top;
+			const xp = mouseX / this.refs.view.offsetWidth * 100;
+			const yp = mouseY / this.refs.view.offsetHeight * 100;
+			this.refs.view.style.backgroundPosition = xp + '% ' + yp + '%';
+		};
 
 		this.click = () => {
-			dialog = document.body.appendChild(document.createElement('mk-image-dialog'));
-			riot.mount dialog, do
-				image: @image
+			riot.mount(document.body.appendChild(document.createElement('mk-image-dialog')), {
+				image: this.image
+			});
+		};
 	</script>
 </mk-images-viewer>
diff --git a/src/web/app/desktop/tags/notifications.tag b/src/web/app/desktop/tags/notifications.tag
index 2db27a4fc..7ba74412e 100644
--- a/src/web/app/desktop/tags/notifications.tag
+++ b/src/web/app/desktop/tags/notifications.tag
@@ -182,32 +182,36 @@
 		this.mixin('user-preview');
 		this.mixin('get-post-summary');
 
-		this.notifications = []
-		this.loading = true
+		this.notifications = [];
+		this.loading = true;
 
 		this.on('mount', () => {
-			this.api 'i/notifications' 
-			}).then((notifications) => {
-				this.notifications = notifications
-				this.loading = false
-				this.update();
-			.catch (err, text-status) ->
-				console.error err
+			this.api('i/notifications').then(notifications => {
+				this.update({
+					loading: false,
+					notifications: notifications
+				});
+			});
 
-			this.stream.on 'notification' this.on-notification
+			this.stream.on('notification', this.onNotification);
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'notification' this.on-notification
+			this.stream.off('notification', this.onNotification);
+		});
 
-		this.on-notification = (notification) => {
-			@notifications.unshift notification
+		this.onNotification = notification => {
+			this.notifications.unshift(notification);
 			this.update();
+		};
 
 		this.on('update', () => {
-			@notifications.forEach (notification) =>
-				date = (new Date notification.created_at).getDate()
-				month = (new Date notification.created_at).getMonth() + 1
-				notification._date = date
-				notification._datetext = month + '月 ' + date + '日'
+			this.notifications.forEach(notification => {
+				const date = new Date(notification.created_at).getDate();
+				const month = new Date(notification.created_at).getMonth() + 1;
+				notification._date = date;
+				notification._datetext = `${month}月 ${date}日`;
+			});
+		});
 	</script>
 </mk-notifications>
diff --git a/src/web/app/desktop/tags/post-detail-sub.tag b/src/web/app/desktop/tags/post-detail-sub.tag
index 24feda9be..f1b3c915c 100644
--- a/src/web/app/desktop/tags/post-detail-sub.tag
+++ b/src/web/app/desktop/tags/post-detail-sub.tag
@@ -108,33 +108,40 @@
 		this.mixin('date-stringify');
 		this.mixin('user-preview');
 
-		this.post = this.opts.post
+		this.post = this.opts.post;
 
-		this.url = CONFIG.url + '/' + this.post.user.username + '/' + this.post.id
+		this.url = CONFIG.url + '/' + this.post.user.username + '/' + this.post.id;
 
-		this.title = @date-stringify this.post.created_at
+		this.title = this.dateStringify(this.post.created_at);
 
 		this.on('mount', () => {
-			if this.post.text?
-				tokens = @analyze this.post.text
-				this.refs.text.innerHTML = @compile tokens
+			if (this.p.text) {
+				const tokens = this.analyze(this.p.text);
 
-				this.refs.text.children.forEach (e) =>
-					if e.tag-name == 'MK-URL' 
-						riot.mount e
+				this.refs.text.innerHTML = this.refs.text.innerHTML.replace('<p class="dummy"></p>', this.compile(tokens));
+
+				this.refs.text.children.forEach(e => {
+					if (e.tagName == 'MK-URL') riot.mount(e);
+				});
+			}
+		});
 
 		this.like = () => {
-			if this.post.is_liked
+			if (this.post.is_liked) {
 				this.api('posts/likes/delete', {
 					post_id: this.post.id
 				}).then(() => {
-					this.post.is_liked = false
+					this.post.is_liked = false;
 					this.update();
-			else
+				});
+			} else {
 				this.api('posts/likes/create', {
 					post_id: this.post.id
 				}).then(() => {
-					this.post.is_liked = true
+					this.post.is_liked = true;
 					this.update();
+				});
+			}
+		};
 	</script>
 </mk-post-detail-sub>
diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag
index 00426ea9b..cc5fbeed8 100644
--- a/src/web/app/desktop/tags/post-detail.tag
+++ b/src/web/app/desktop/tags/post-detail.tag
@@ -335,102 +335,120 @@
 		this.mixin('date-stringify');
 		this.mixin('NotImplementedException');
 
-		this.fetching = true
-		this.loading-context = false
-		this.content = null
-		this.post = null
+		this.fetching = true;
+		this.loadingContext = false;
+		this.content = null;
+		this.post = null;
 
 		this.on('mount', () => {
-
 			this.api('posts/show', {
 				post_id: this.opts.post
-			}).then((post) => {
-				this.fetching = false
-				this.post = post
+			}).then(post => {
+				const isRepost = post.repost != null;
+				const p = isRepost ? post.repost : post;
+				this.update({
+					fetching: false,
+					post: post,
+					isRepost: isRepost,
+					p: p,
+					title: this.dateStringify(p.created_at)
+				});
+
 				this.trigger('loaded');
 
-				this.is-repost = this.post.repost?
-				this.p = if @is-repost then this.post.repost else this.post
+				if (this.p.text) {
+					const tokens = this.analyze(this.p.text);
 
-				this.title = @date-stringify this.p.created_at
+					this.refs.text.innerHTML = this.compile(tokens);
 
-				this.update();
-
-				if this.p.text?
-					tokens = @analyze this.p.text
-					this.refs.text.innerHTML = @compile tokens
-
-					this.refs.text.children.forEach (e) =>
-						if e.tag-name == 'MK-URL' 
-							riot.mount e
+					this.refs.text.children.forEach(e => {
+						if (e.tagName == 'MK-URL') riot.mount(e);
+					});
 
 					// URLをプレビュー
 					tokens
-						.filter (t) -> t.type == 'link' 
-						.map (t) =>
-							this.preview = this.refs.text.appendChild(document.createElement('mk-url-preview'));
- 							riot.mount this.preview, do
-								url: t.content
+					.filter(t => t.type == 'link')
+					.map(t => {
+						riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
+							url: t.content
+						});
+					});
+				}
 
 				// Get likes
 				this.api('posts/likes', {
-					post_id: this.p.id
+					post_id: this.p.id,
 					limit: 8
-				}).then((likes) => {
-					this.likes = likes
-					this.update();
+				}).then(likes => {
+					this.update({
+						likes: likes
+					});
+				});
 
 				// Get reposts
 				this.api('posts/reposts', {
-					post_id: this.p.id
+					post_id: this.p.id,
 					limit: 8
-				}).then((reposts) => {
-					this.reposts = reposts
-					this.update();
+				}).then(reposts => {
+					this.update({
+						reposts: reposts
+					});
+				});
 
 				// Get replies
 				this.api('posts/replies', {
-					post_id: this.p.id
+					post_id: this.p.id,
 					limit: 8
-				}).then((replies) => {
-					this.replies = replies
-					this.update();
-
-				this.update();
+				}).then(replies => {
+					this.update({
+						replies: replies
+					});
+				});
+			});
+		});
 
 		this.reply = () => {
-			form = document.body.appendChild(document.createElement('mk-post-form-window'));
- 			riot.mount form, do
+			riot.mount(document.body.appendChild(document.createElement('mk-post-form-window')), {
 				reply: this.p
+			});
+		};
 
 		this.repost = () => {
-			form = document.body.appendChild(document.createElement('mk-repost-form-window'));
- 			riot.mount form, do
+			riot.mount(document.body.appendChild(document.createElement('mk-repost-form-window')), {
 				post: this.p
+			});
+		};
 
 		this.like = () => {
-			if this.p.is_liked
+			if (this.p.is_liked) {
 				this.api('posts/likes/delete', {
 					post_id: this.p.id
 				}).then(() => {
-					this.p.is_liked = false
+					this.p.is_liked = false;
 					this.update();
-			else
+				});
+			} else {
 				this.api('posts/likes/create', {
 					post_id: this.p.id
 				}).then(() => {
-					this.p.is_liked = true
+					this.p.is_liked = true;
 					this.update();
+				});
+			}
+		};
 
-		this.load-context = () => {
-			this.loading-context = true
+		this.loadContext = () => {
+			this.loadingContext = true;
 
-			// Get context
+			// Fetch context
 			this.api('posts/context', {
 				post_id: this.p.reply_to_id
-			}).then((context) => {
-				this.context = context.reverse!
-				this.loading-context = false
-				this.update();
+			}).then(context => {
+				this.update({
+					loadContext: false,
+					content: context.reverse()
+				});
+			});
+		};
 	</script>
 </mk-post-detail>
diff --git a/src/web/app/desktop/tags/post-form-window.tag b/src/web/app/desktop/tags/post-form-window.tag
index 8f5bf1a51..4f2ea2538 100644
--- a/src/web/app/desktop/tags/post-form-window.tag
+++ b/src/web/app/desktop/tags/post-form-window.tag
@@ -32,24 +32,31 @@
 
 	</style>
 	<script>
-		this.uploading-files = []
-		this.files = []
+		this.uploadingFiles = [];
+		this.files = [];
 
 		this.on('mount', () => {
 			this.refs.window.refs.form.focus();
 
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
 
 			this.refs.window.refs.form.on('post', () => {
 				this.refs.window.close();
+			});
 
-			this.refs.window.refs.form.on('change-uploading-files', (files) => {
-				this.uploading-files = files
-				this.update();
+			this.refs.window.refs.form.on('change-uploading-files', files => {
+				this.update({
+					uploadingFiles: files
+				});
+			});
 
-			this.refs.window.refs.form.on('change-files', (files) => {
-				this.files = files
-				this.update();
+			this.refs.window.refs.form.on('change-files', files => {
+				this.update({
+					files: files
+				});
+			});
+		});
 	</script>
 </mk-post-form-window>
diff --git a/src/web/app/desktop/tags/post-preview.tag b/src/web/app/desktop/tags/post-preview.tag
index 06008da3c..458a6f83f 100644
--- a/src/web/app/desktop/tags/post-preview.tag
+++ b/src/web/app/desktop/tags/post-preview.tag
@@ -86,8 +86,8 @@
 		this.mixin('date-stringify');
 		this.mixin('user-preview');
 
-		this.post = this.opts.post
+		this.post = this.opts.post;
 
-		this.title = @date-stringify this.post.created_at
+		this.title = this.dateStringify(this.post.created_at);
 	</script>
 </mk-post-preview>
diff --git a/src/web/app/desktop/tags/progress-dialog.tag b/src/web/app/desktop/tags/progress-dialog.tag
index cba4e3404..760f869f6 100644
--- a/src/web/app/desktop/tags/progress-dialog.tag
+++ b/src/web/app/desktop/tags/progress-dialog.tag
@@ -75,20 +75,25 @@
 
 	</style>
 	<script>
-		this.title = this.opts.title
-		this.value = parse-int this.opts.value, 10
-		this.max = parse-int this.opts.max, 10
+		this.title = this.opts.title;
+		this.value = parseInt(this.opts.value, 10);
+		this.max = parseInt(this.opts.max, 10);
 
 		this.on('mount', () => {
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
+		});
 
-		this.update-progress = (value, max) => {
-			this.value = parse-int value, 10
-			this.max = parse-int max, 10
-			this.update();
+		this.updateProgress = (value, max) => {
+			this.update({
+				value: parseInt(value, 10),
+				max: parseInt(max, 10)
+			});
+		};
 
 		this.close = () => {
 			this.refs.window.close();
+		};
 	</script>
 </mk-progress-dialog>
diff --git a/src/web/app/desktop/tags/repost-form-window.tag b/src/web/app/desktop/tags/repost-form-window.tag
index d7521caab..75fe9f482 100644
--- a/src/web/app/desktop/tags/repost-form-window.tag
+++ b/src/web/app/desktop/tags/repost-form-window.tag
@@ -12,25 +12,32 @@
 
 	</style>
 	<script>
-		this.on-document-keydown = (e) => {
-			tag = e.target.tag-name.to-lower-case!
-			if tag != 'input' and tag != 'textarea' 
-				if e.which == 27 // Esc
+		this.onDocumentKeydown = e => {
+			if (e.target.tagName != 'INPUT' && e.target.tagName != 'TEXTAREA') {
+				if (e.which == 27) { // Esc
 					this.refs.window.close();
+				}
+			}
+		};
 
 		this.on('mount', () => {
 			this.refs.window.refs.form.on('cancel', () => {
 				this.refs.window.close();
+			});
 
 			this.refs.window.refs.form.on('posted', () => {
 				this.refs.window.close();
+			});
 
-			document.addEventListener 'keydown' this.on-document-keydown
+			document.addEventListener('keydown', this.onDocumentKeydown);
 
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
+		});
 
 		this.on('unmount', () => {
-			document.removeEventListener 'keydown' this.on-document-keydown
+			document.removeEventListener('keydown', this.onDocumentKeydown);
+		});
 	</script>
 </mk-repost-form-window>
diff --git a/src/web/app/desktop/tags/repost-form.tag b/src/web/app/desktop/tags/repost-form.tag
index 7d309bf75..de10a37f0 100644
--- a/src/web/app/desktop/tags/repost-form.tag
+++ b/src/web/app/desktop/tags/repost-form.tag
@@ -117,28 +117,31 @@
 		this.mixin('api');
 		this.mixin('notify');
 
-		this.wait = false
-		this.quote = false
+		this.wait = false;
+		this.quote = false;
 
 		this.cancel = () => {
 			this.trigger('cancel');
+		};
 
 		this.ok = () => {
-			this.wait = true
+			this.wait = true;
 			this.api('posts/create', {
-				repost_id: this.opts.post.id
-				text: if this.quote then this.refs.text.value else undefined
-			}).then((data) => {
+				repost_id: this.opts.post.id,
+				text: this.quote ? this.refs.text.value : undefined
+			}).then(data => {
 				this.trigger('posted');
-				@notify 'Repostしました!'
-			.catch (err) =>
-				console.error err
-				@notify 'Repostできませんでした'
+				this.notify('Repostしました!');
+			}).catch(err => {
+				this.notify('Repostできませんでした');
 			}).then(() => {
-				this.wait = false
-				this.update();
+				this.update({
+					wait: false
+				});
+			});
 
 		this.onquote = () => {
-			this.quote = true
+			this.quote = true;
+		};
 	</script>
 </mk-repost-form>
diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag
index e6781f4a2..832299e32 100644
--- a/src/web/app/desktop/tags/ui.tag
+++ b/src/web/app/desktop/tags/ui.tag
@@ -31,6 +31,7 @@
 			if (e.which == 80 || e.which == 78) { // p or n
 				e.preventDefault();
 				this.openPostForm();
+			}
 		};
 	</script>
 </mk-ui>
diff --git a/src/web/app/desktop/tags/user-friends-graph.tag b/src/web/app/desktop/tags/user-friends-graph.tag
deleted file mode 100644
index 8932d596f..000000000
--- a/src/web/app/desktop/tags/user-friends-graph.tag
+++ /dev/null
@@ -1,67 +0,0 @@
-<mk-user-friends-graph>
-	<canvas ref="canv" width="750" height="250"></canvas>
-	<style>
-		:scope
-			display block
-			width 750px
-			height 250px
-
-	</style>
-	<script>
-		this.mixin('api');
-		this.mixin('is-promise');
-
-		this.user = null
-		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
-
-		this.on('mount', () => {
-			user <~ this.user-promise.then
-			this.user = user
-			this.update();
-
-			this.api('aggregation/users/followers', {
-				user_id: this.user.id
-				limit: 30days
-			}).then((followers) => {
-				followers = followers.reverse!
-
-				this.api('aggregation/users/following', {
-					user_id: this.user.id
-					limit: 30days
-				}).then((following) => {
-					following = following.reverse!
-
-					new Chart this.refs.canv, do
-						type: 'line' 
-						data:
-							labels: following.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
-							datasets: [
-								{
-									label: 'フォロー' 
-									data: following.map (x) => x.count
-									line-tension: 0
-									border-width: 2
-									fill: true
-									background-color: 'rgba(127, 221, 64, 0.2)'
-									point-background-color: '#fff' 
-									point-radius: 4
-									point-border-width: 2
-									border-color: '#7fdd40' 
-								},
-								{
-									label: 'フォロワー' 
-									data: followers.map (x) => x.count
-									line-tension: 0
-									border-width: 2
-									fill: true
-									background-color: 'rgba(255, 99, 132, 0.2)'
-									point-background-color: '#fff' 
-									point-radius: 4
-									point-border-width: 2
-									border-color: '#FF6384' 
-								}
-							]
-						options:
-							responsive: false
-	</script>
-</mk-user-friends-graph>
diff --git a/src/web/app/desktop/tags/user-likes-graph.tag b/src/web/app/desktop/tags/user-likes-graph.tag
deleted file mode 100644
index 5639ee36e..000000000
--- a/src/web/app/desktop/tags/user-likes-graph.tag
+++ /dev/null
@@ -1,42 +0,0 @@
-<mk-user-likes-graph>
-	<canvas ref="canv" width="750" height="250"></canvas>
-	<style>
-		:scope
-			display block
-			width 750px
-			height 250px
-
-	</style>
-	<script>
-		this.mixin('api');
-		this.mixin('is-promise');
-
-		this.user = null
-		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
-
-		this.on('mount', () => {
-			user <~ this.user-promise.then
-			this.user = user
-			this.update();
-
-			this.api('aggregation/users/like', {
-				user_id: this.user.id
-				limit: 30days
-			}).then((likes) => {
-				likes = likes.reverse!
-
-				new Chart this.refs.canv, do
-					type: 'bar' 
-					data:
-						labels: likes.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
-						datasets: [
-							{
-								label: 'いいねした数' 
-								data: likes.map (x) => x.count
-								background-color: '#F7796C' 
-							}
-						]
-					options:
-						responsive: false
-	</script>
-</mk-user-likes-graph>

From 030dbbc2ebc59f6f23804cf648e37112b6dd8aba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?syuilo=E2=AD=90=EF=B8=8F?= <Syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 21:48:00 +0900
Subject: [PATCH 27/32] Update user-profile.tag

---
 src/web/app/desktop/tags/user-profile.tag | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/web/app/desktop/tags/user-profile.tag b/src/web/app/desktop/tags/user-profile.tag
index 36c9f7f95..03697fd5f 100644
--- a/src/web/app/desktop/tags/user-profile.tag
+++ b/src/web/app/desktop/tags/user-profile.tag
@@ -80,20 +80,22 @@
 
 	</style>
 	<script>
-		this.age = require 's-age' 
+		this.age = require('s-age'); 
 
 		this.mixin('i');
 
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
-		this.show-following = () => {
-			window = document.body.appendChild(document.createElement('mk-user-following-window'));
- 			riot.mount window, do
+		this.showFollowing = () => {
+ 			riot.mount(document.body.appendChild(document.createElement('mk-user-following-window')), {
 				user: this.user
+			});
+		};
 
-		this.show-followers = () => {
-			window = document.body.appendChild(document.createElement('mk-user-followers-window'));
- 			riot.mount window, do
+		this.showFollowers = () => {
+ 			riot.mount(document.body.appendChild(document.createElement('mk-user-followers-window')), {
 				user: this.user
+			});
+		};
 	</script>
 </mk-user-profile>

From 03506738621046944f35131d53f0a7f243698510 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?syuilo=E2=AD=90=EF=B8=8F?= <Syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 21:51:58 +0900
Subject: [PATCH 28/32] Update user.tag

---
 src/web/app/desktop/tags/user.tag | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/web/app/desktop/tags/user.tag b/src/web/app/desktop/tags/user.tag
index 9b64cf08e..c12873618 100644
--- a/src/web/app/desktop/tags/user.tag
+++ b/src/web/app/desktop/tags/user.tag
@@ -34,18 +34,21 @@
 	<script>
 		this.mixin('api');
 
-		this.username = this.opts.user
-		this.page = if this.opts.page? then this.opts.page else 'home' 
-		this.fetching = true
-		this.user = null
+		this.username = this.opts.user;
+		this.page = this.opts.page ? this.opts.page : 'home';
+		this.fetching = true;
+		this.user = null;
 
 		this.on('mount', () => {
 			this.api('users/show', {
 				username: this.username
-			}).then((user) => {
-				this.fetching = false
-				this.user = user
-				this.update();
+			}).then(user => {
+				this.update({
+					fetching: false,
+					user: user
+				});
 				this.trigger('loaded');
+			});
+		});
 	</script>
 </mk-user>

From 65d03dc9dad6ca85d0093b58b5fbef0bfa8e14b7 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 21 Feb 2017 23:46:37 +0900
Subject: [PATCH 29/32] wip

---
 src/web/app/desktop/tags/post-form.tag        | 202 +++++++++---------
 src/web/app/desktop/tags/settings-window.tag  |   3 +
 src/web/app/desktop/tags/settings.tag         |  58 +++--
 src/web/app/desktop/tags/stream-indicator.tag |  20 +-
 4 files changed, 143 insertions(+), 140 deletions(-)

diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index 737c77dbf..9ef7a2504 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -305,161 +305,159 @@
 
 	</style>
 	<script>
-		get-cat = require('../../common/scripts/get-cat');
+		getCat = require('../../common/scripts/get-cat');
 
 		this.mixin('api');
 		this.mixin('notify');
 		this.mixin('autocomplete');
 
-		this.wait = false
-		this.uploadings = []
-		this.files = []
-		this.autocomplete = null
-		this.poll = false
+		this.wait = false;
+		this.uploadings = [];
+		this.files = [];
+		this.autocomplete = null;
+		this.poll = false;
 
-		this.in-reply-to-post = this.opts.reply
+		this.inReplyToPost = this.opts.reply;
 
 		// https://github.com/riot/riot/issues/2080
-		if @in-reply-to-post == '' then this.in-reply-to-post = null
+		if (this.inReplyToPost == '') this.inReplyToPost = null;
 
 		this.on('mount', () => {
-			this.refs.uploader.on('uploaded', (file) => {
-				this.addFile file
+			this.refs.uploader.on('uploaded', file => {
+				this.addFile(file);
+			});
 
-			this.refs.uploader.on('change-uploads', (uploads) => {
-				this.trigger 'change-uploading-files' uploads
+			this.refs.uploader.on('change-uploads', uploads => {
+				this.trigger('change-uploading-files', uploads);
+			});
 
-			this.autocomplete = new @Autocomplete this.refs.text
-			@autocomplete.attach!
+			this.autocomplete = new this.Autocomplete(this.refs.text);
+			this.autocomplete.attach();
+		});
 
 		this.on('unmount', () => {
-			@autocomplete.detach!
+			this.autocomplete.detach();
+		});
 
 		this.focus = () => {
 			this.refs.text.focus();
+		};
 
 		this.clear = () => {
-			this.refs.text.value = ''
-			this.files = []
+			this.refs.text.value = '';
+			this.files = [];
 			this.trigger('change-files');
 			this.update();
+		};
 
-		this.ondragover = (e) => {
+		this.ondragover = e => {
 			e.stopPropagation();
-			this.draghover = true
-			// ドラッグされてきたものがファイルだったら
-			if e.dataTransfer.effectAllowed == 'all' 
-				e.dataTransfer.dropEffect = 'copy' 
-			else
-				e.dataTransfer.dropEffect = 'move' 
-			return false
+			this.draghover = true;
+			e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
+			return false;
+		};
 
-		this.ondragenter = (e) => {
-			this.draghover = true
+		this.ondragenter = e => {
+			this.draghover = true;
+		};
 
-		this.ondragleave = (e) => {
-			this.draghover = false
+		this.ondragleave = e => {
+			this.draghover = false;
+		};
 
-		this.ondrop = (e) => {
+		this.ondrop = e => {
 			e.preventDefault();
 			e.stopPropagation();
-			this.draghover = false
+			this.draghover = false;
 
 			// ファイルだったら
-			if e.dataTransfer.files.length > 0
-				Array.prototype.forEach.call e.dataTransfer.files, (file) =>
-					@upload file
-				return false
+			if (e.dataTransfer.files.length > 0) {
+				e.dataTransfer.files.forEach(this.upload);
+			}
 
-			// データ取得
-			data = e.dataTransfer.get-data 'text'
-			if !data?
-				return false
+			return false;
+		};
 
-			try
-				// パース
-				obj = JSON.parse data
+		this.onkeydown = e => {
+			if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.meta-key)) this.post();
+		};
 
-				// (ドライブの)ファイルだったら
-				if obj.type == 'file' 
-					this.addFile obj.file
-			catch
-				// ignore
+		this.onpaste = e => {
+			e.clipboardData.items.forEach(item => {
+				if (item.kind == 'file') {
+					this.upload(item.getAsFile());
+				}
+			});
+		};
 
-			return false
-
-		this.onkeydown = (e) => {
-			if (e.which == 10 || e.which == 13) && (e.ctrlKey || e.meta-key)
-				this.post!
-
-		this.onpaste = (e) => {
-			data = e.clipboardData
-			items = data.items
-			for i from 0 to items.length - 1
-				item = items[i]
-				switch (item.kind)
-					| 'file' =>
-						@upload item.getAsFile();
-
-		this.select-file = () => {
+		this.selectFile = () => {
 			this.refs.file.click();
+		};
 
-		this.select-file-from-drive = () => {
-			browser = document.body.appendChild(document.createElement('mk-select-file-from-drive-window'));
- 			i = riot.mount browser, do
+		this.selectFileFromDrive = () => {
+			const i = riot.mount(document.body.appendChild(document.createElement('mk-select-file-from-drive-window')), {
 				multiple: true
-			i[0].one 'selected' (files) =>
-				files.forEach this.addFile
+			})[0];
+			i.one('selected', files => {
+				files.forEach(this.addFile);
+			});
+		};
 
-		this.change-file = () => {
-			files = this.refs.file.files
-			for i from 0 to files.length - 1
-				file = files.item i
-				@upload file
+		this.changeFile = () => {
+			this.refs.file.files.forEach(this.upload);
+		};
 
-		this.upload = (file) => {
-			this.refs.uploader.upload file
+		this.upload = file => {
+			this.refs.uploader.upload(file);
+		};
 
-		this.add-file = (file) => {
-			file._remove = =>
-				this.files = this.files.filter (x) -> x.id != file.id
-				this.trigger 'change-files' this.files
+		this.addFile = file => {
+			file._remove = () => {
+				this.files = this.files.filter(x => x.id != file.id);
+				this.trigger('change-files', this.files);
 				this.update();
+			};
 
-			this.files.push file
-			this.trigger 'change-files' this.files
+			this.files.push(file);
+			this.trigger('change-files', this.files);
 			this.update();
+		};
 
-		this.add-poll = () => {
-			this.poll = true
+		this.addPoll = () => {
+			this.poll = true;
+		};
 
-		this.on-poll-destroyed = () => {
-			@update do
+		this.onPollDestroyed = () => {
+			this.update({
 				poll: false
+			});
+		};
 
-		this.post = (e) => {
-			this.wait = true
+		this.post = e => {
+			this.wait = true;
 
-			files = if this.files? and this.files.length > 0
-				then this.files.map (f) -> f.id
-				else undefined
+			const files = this.files && this.files.length > 0
+				? this.files.map(f => f.id)
+				: undefined;
 
 			this.api('posts/create', {
-				text: this.refs.text.value
-				media_ids: files
-				reply_to_id: if @in-reply-to-post? then @in-reply-to-post.id else undefined
-				poll: if this.poll then this.refs.poll.get! else undefined
-			}).then((data) => {
+				text: this.refs.text.value,
+				media_ids: files,
+				reply_to_id: this.inReplyToPost ? this.inReplyToPost.id : undefined,
+				poll: this.poll ? this.refs.poll.get() : undefined
+			}).then(data => {
 				this.trigger('post');
-				@notify if @in-reply-to-post? then '返信しました!' else '投稿しました!'
-			.catch (err) =>
-				console.error err
-				@notify '投稿できませんでした'
+				this.notify(this.inReplyToPost ? '返信しました!' : '投稿しました!');
+			}).catch(err => {
+				this.notify('投稿できませんでした');
 			}).then(() => {
-				this.wait = false
-				this.update();
+				this.update({
+					wait: false
+				});
+			});
 
 		this.cat = () => {
-			this.refs.text.value = this.refs.text.value + get-cat!
+			this.refs.text.value += getCat();
+		};
 	</script>
 </mk-post-form>
diff --git a/src/web/app/desktop/tags/settings-window.tag b/src/web/app/desktop/tags/settings-window.tag
index b3f0bb457..cb78921d4 100644
--- a/src/web/app/desktop/tags/settings-window.tag
+++ b/src/web/app/desktop/tags/settings-window.tag
@@ -18,8 +18,11 @@
 		this.on('mount', () => {
 			this.refs.window.on('closed', () => {
 				this.unmount();
+			});
+		});
 
 		this.close = () => {
 			this.refs.window.close();
+		};
 	</script>
 </mk-settings-window>
diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag
index e43a512af..544e41c25 100644
--- a/src/web/app/desktop/tags/settings.tag
+++ b/src/web/app/desktop/tags/settings.tag
@@ -47,11 +47,6 @@
 				<p>読み込みを高速化する</p>
 				<p>API通信時に新鮮なユーザー情報をキャッシュすることでフェッチのオーバーヘッドを無くします。(実験的)</p>
 			</label>
-			<label class="checkbox">
-				<input type="checkbox" checked={ I.data.debug } onclick={ updateDebug }/>
-				<p>開発者モード</p>
-				<p>デバッグ等の開発者モードを有効にします。</p>
-			</label>
 			<label class="checkbox">
 				<input type="checkbox" checked={ I.data.nya } onclick={ updateNya }/>
 				<p><i>な</i>を<i>にゃ</i>に変換する</p>
@@ -200,44 +195,47 @@
 	<script>
 		this.mixin('i');
 		this.mixin('api');
+		this.mixin('notify');
 		this.mixin('dialog');
 		this.mixin('update-avatar');
 
-		this.page = 'account' 
+		this.page = 'account';
 
-		this.set-page = (page) => {
-			this.page = page
+		this.setPage = page => {
+			this.page = page;
+		};
 
 		this.avatar = () => {
-			@update-avatar this.I
+			this.updateAvatar(this.I);
+		};
 
-		this.update-account = () => {
+		this.updateAccount = () => {
 			this.api('i/update', {
-				name: this.refs.account-name.value
-				location: this.refs.account-location.value
-				bio: this.refs.account-bio.value
-				birthday: this.refs.account-birthday.value
-			}).then((i) => {
-				alert 'ok' 
-			.catch (err) =>
-				console.error err
+				name: this.refs.accountName.value,
+				location: this.refs.accountLocation.value,
+				bio: this.refs.accountBio.value,
+				birthday: this.refs.accountBirthday.value
+			}).then(() => {
+				this.notify('プロフィールを更新しました');
+			});
+		};
 
-		this.update-cache = () => {
-			this.I.data.cache = !this.I.data.cache
+		this.updateCache = () => {
+			this.I.data.cache = !this.I.data.cache;
 			this.api('i/appdata/set', {
-				data: JSON.stringify do
+				data: JSON.stringify({
 					cache: this.I.data.cache
+				})
+			});
+		};
 
-		this.update-debug = () => {
-			this.I.data.debug = !this.I.data.debug
+		this.updateNya = () => {
+			this.I.data.nya = !this.I.data.nya;
 			this.api('i/appdata/set', {
-				data: JSON.stringify do
-					debug: this.I.data.debug
-
-		this.update-nya = () => {
-			this.I.data.nya = !this.I.data.nya
-			this.api('i/appdata/set', {
-				data: JSON.stringify do
+				data: JSON.stringify({
 					nya: this.I.data.nya
+				})
+			});
+		};
 	</script>
 </mk-settings>
diff --git a/src/web/app/desktop/tags/stream-indicator.tag b/src/web/app/desktop/tags/stream-indicator.tag
index 9ca311c47..6192b642f 100644
--- a/src/web/app/desktop/tags/stream-indicator.tag
+++ b/src/web/app/desktop/tags/stream-indicator.tag
@@ -32,23 +32,27 @@
 		this.on('before-mount', () => {
 			this.state = this.getStreamState();
 
-			if this.state == 'connected' 
-				this.root.style.opacity = 0
+			if (this.state == 'connected') {
+				this.root.style.opacity = 0;
+			}
+		});
 
-		this.stream-state-ev.on('connected', () => {
+		this.streamStateEv.on('connected', () => {
 			this.state = this.getStreamState();
 			this.update();
-			setTimeout =>
+			setTimeout(() => {
 				Velocity(this.root, {
 					opacity: 0
-				} 200ms 'linear' 
-			, 1000ms
+				}, 200, 'linear');
+			}, 1000);
+		});
 
-		this.stream-state-ev.on('closed', () => {
+		this.streamStateEv.on('closed', () => {
 			this.state = this.getStreamState();
 			this.update();
 			Velocity(this.root, {
 				opacity: 1
-			} 0ms
+			}, 0);
+		});
 	</script>
 </mk-stream-indicator>

From 2a1fab34df0ae5a6e8bdaf5cd731ae50545328b6 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 22 Feb 2017 01:05:23 +0900
Subject: [PATCH 30/32] wip

---
 src/web/app/auth/tags/form.tag                |  12 +-
 src/web/app/auth/tags/index.tag               |  62 +--
 src/web/app/common/tags/core-error.tag        |   7 +-
 src/web/app/common/tags/index.js              |   2 +-
 src/web/app/common/tags/ripple-string.tag     |  26 --
 .../tags/stream-indicator.tag                 |  17 +-
 src/web/app/desktop/tags/index.js             |   1 -
 src/web/app/desktop/tags/post-form.tag        |   1 +
 src/web/app/dev/tags/new-app-form.tag         | 105 ++---
 src/web/app/dev/tags/pages/app.tag            |  14 +-
 src/web/app/dev/tags/pages/apps.tag           |  13 +-
 src/web/app/dev/tags/pages/index.tag          |   5 -
 src/web/app/mobile/tags/drive.tag             | 366 +++++++++---------
 src/web/app/mobile/tags/drive/file-viewer.tag |  21 +-
 src/web/app/mobile/tags/drive/file.tag        |  14 +-
 src/web/app/mobile/tags/drive/folder.tag      |   7 +-
 src/web/app/mobile/tags/follow-button.tag     |  78 ++--
 src/web/app/mobile/tags/images-viewer.tag     |   7 +-
 src/web/app/mobile/tags/index.js              |   1 -
 .../app/mobile/tags/notification-preview.tag  |   2 +-
 src/web/app/mobile/tags/notification.tag      |   2 +-
 src/web/app/mobile/tags/notifications.tag     |  41 +-
 src/web/app/mobile/tags/notify.tag            |  24 +-
 src/web/app/mobile/tags/post-detail.tag       | 116 +++---
 src/web/app/mobile/tags/post-form.tag         | 134 ++++---
 src/web/app/mobile/tags/search-posts.tag      |  12 +-
 src/web/app/mobile/tags/search.tag            |   5 +-
 src/web/app/mobile/tags/stream-indicator.tag  |  54 ---
 src/web/app/mobile/tags/sub-post-content.tag  |  16 +-
 src/web/app/mobile/tags/timeline-post.tag     |   2 +-
 src/web/app/mobile/tags/ui-header.tag         |   6 +-
 src/web/app/mobile/tags/ui-nav.tag            |  10 +-
 src/web/app/mobile/tags/ui.tag                |  41 +-
 src/web/app/mobile/tags/user-followers.tag    |  15 +-
 src/web/app/mobile/tags/user-following.tag    |  15 +-
 src/web/app/mobile/tags/user-timeline.tag     |  18 +-
 src/web/app/mobile/tags/users-list.tag        |  67 ++--
 37 files changed, 680 insertions(+), 659 deletions(-)
 delete mode 100644 src/web/app/common/tags/ripple-string.tag
 rename src/web/app/{desktop => common}/tags/stream-indicator.tag (70%)
 delete mode 100644 src/web/app/mobile/tags/stream-indicator.tag

diff --git a/src/web/app/auth/tags/form.tag b/src/web/app/auth/tags/form.tag
index 619c71065..4a236f759 100644
--- a/src/web/app/auth/tags/form.tag
+++ b/src/web/app/auth/tags/form.tag
@@ -108,19 +108,23 @@
 	<script>
 		this.mixin('api');
 
-		this.session = this.opts.session
-		this.app = @session.app
+		this.session = this.opts.session;
+		this.app = this.session.app;
 
 		this.cancel = () => {
 			this.api('auth/deny', {
-				token: @session.token
+				token: this.session.token
 			}).then(() => {
 				this.trigger('denied');
+			});
+		};
 
 		this.accept = () => {
 			this.api('auth/accept', {
-				token: @session.token
+				token: this.session.token
 			}).then(() => {
 				this.trigger('accepted');
+			});
+		};
 	</script>
 </mk-form>
diff --git a/src/web/app/auth/tags/index.tag b/src/web/app/auth/tags/index.tag
index e52aeed4d..f80e9dd1b 100644
--- a/src/web/app/auth/tags/index.tag
+++ b/src/web/app/auth/tags/index.tag
@@ -91,47 +91,57 @@
 		this.mixin('i');
 		this.mixin('api');
 
-		this.state = null
-		this.fetching = true
+		this.state = null;
+		this.fetching = true;
 
-		this.token = window.location.href.split '/' .pop!
+		this.token = window.location.href.split('/').pop();
 
 		this.on('mount', () => {
-			if not this.SIGNIN then return
+			if (!this.SIGNIN) return;
 
 			// Fetch session
 			this.api('auth/session/show', {
-				token: @token
-			}).then((session) => {
-				this.session = session
-				this.fetching = false
+				token: this.token
+			}).then(session => {
+				this.session = session;
+				this.fetching = false;
 
 				// 既に連携していた場合
-				if @session.app.is_authorized
+				if (this.session.app.is_authorized) {
 					this.api('auth/accept', {
-						token: @session.token
+						token: this.session.token
 					}).then(() => {
-						@accepted!
-				else
-					this.state = 'waiting' 
-					this.update();
+						this.accepted();
+					});
+				} else {
+					this.update({
+						state: 'waiting'
+					});
 
 					this.refs.form.on('denied', () => {
-						this.state = 'denied' 
-						this.update();
+						this.update({
+							state: 'denied'
+						});
+					});
 
-					this.refs.form.on 'accepted' @accepted
-
-			.catch (error) =>
-				this.fetching = false
-				this.state = 'fetch-session-error' 
-				this.update();
+					this.refs.form.on('accepted', this.accepted);
+				}
+			}).catch(error => {
+				this.update({
+					fetching: false,
+					state: 'fetch-session-error'
+				});
+			});
+		});
 
 		this.accepted = () => {
-			this.state = 'accepted' 
-			this.update();
+			this.update({
+				state: 'accepted'
+			});
 
-			if @session.app.callback_url
-				location.href = @session.app.callback_url + '?token=' + @session.token
+			if (this.session.app.callback_url) {
+				location.href = this.session.app.callback_url + '?token=' + this.session.token;
+			}
+		};
 	</script>
 </mk-index>
diff --git a/src/web/app/common/tags/core-error.tag b/src/web/app/common/tags/core-error.tag
index e74e205af..feac70fbe 100644
--- a/src/web/app/common/tags/core-error.tag
+++ b/src/web/app/common/tags/core-error.tag
@@ -1,8 +1,7 @@
 <mk-core-error>
-	<!--i: i.fa.fa-times-circle--><img src="/_/resources/error.jpg" alt=""/>
-	<h1>
-		<mk-ripple-string>サーバーに接続できません</mk-ripple-string>
-	</h1>
+	<!--i: i.fa.fa-times-circle-->
+	<img src="/_/resources/error.jpg" alt=""/>
+	<h1>サーバーに接続できません</h1>
 	<p class="text">インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから<a onclick={ retry }>再度お試し</a>ください。</p>
 	<p class="thanks">いつもMisskeyをご利用いただきありがとうございます。</p>
 	<style>
diff --git a/src/web/app/common/tags/index.js b/src/web/app/common/tags/index.js
index 21d817dbd..90f03825e 100644
--- a/src/web/app/common/tags/index.js
+++ b/src/web/app/common/tags/index.js
@@ -1,7 +1,6 @@
 require('./core-error.tag');
 require('./url.tag');
 require('./url-preview.tag');
-require('./ripple-string.tag');
 require('./time.tag');
 require('./file-type-icon.tag');
 require('./uploader.tag');
@@ -24,3 +23,4 @@ require('./messaging/room.tag');
 require('./messaging/message.tag');
 require('./messaging/index.tag');
 require('./messaging/form.tag');
+require('./stream-indicator.tag');
diff --git a/src/web/app/common/tags/ripple-string.tag b/src/web/app/common/tags/ripple-string.tag
deleted file mode 100644
index f6cd8c94d..000000000
--- a/src/web/app/common/tags/ripple-string.tag
+++ /dev/null
@@ -1,26 +0,0 @@
-<mk-ripple-string><yield/>
-	<style>
-		:scope
-			display inline
-
-			> span
-				animation ripple-string 5s infinite ease-in-out both
-
-			@keyframes ripple-string
-				0%, 50%, 100%
-					opacity 1
-				25%
-					opacity 0.5
-
-	</style>
-	<script>
-		this.on('mount', () => {
-			text = this.root.innerHTML
-			this.root.innerHTML = ''
-			(text.split '').forEach (c, i) =>
-				ce = document.createElement 'span' 
-				ce.innerHTML = c
-				ce.style.animationDelay = (i / 10) + 's'
-				this.root.appendChild ce
-	</script>
-</mk-ripple-string>
diff --git a/src/web/app/desktop/tags/stream-indicator.tag b/src/web/app/common/tags/stream-indicator.tag
similarity index 70%
rename from src/web/app/desktop/tags/stream-indicator.tag
rename to src/web/app/common/tags/stream-indicator.tag
index 6192b642f..7d343a438 100644
--- a/src/web/app/desktop/tags/stream-indicator.tag
+++ b/src/web/app/common/tags/stream-indicator.tag
@@ -1,9 +1,16 @@
 <mk-stream-indicator>
-	<p if={ state == 'initializing' }><i class="fa fa-spinner fa-spin"></i><span>接続中
-			<mk-ellipsis></mk-ellipsis></span></p>
-	<p if={ state == 'reconnecting' }><i class="fa fa-spinner fa-spin"></i><span>切断されました 接続中
-			<mk-ellipsis></mk-ellipsis></span></p>
-	<p if={ state == 'connected' }><i class="fa fa-check"></i><span>接続完了</span></p>
+	<p if={ state == 'initializing' }>
+		<i class="fa fa-spinner fa-spin"></i>
+		<span>接続中<mk-ellipsis></mk-ellipsis></span>
+	</p>
+	<p if={ state == 'reconnecting' }>
+		<i class="fa fa-spinner fa-spin"></i>
+		<span>切断されました 接続中<mk-ellipsis></mk-ellipsis></span>
+	</p>
+	<p if={ state == 'connected' }>
+		<i class="fa fa-check"></i>
+		<span>接続完了</span>
+	</p>
 	<style>
 		:scope
 			display block
diff --git a/src/web/app/desktop/tags/index.js b/src/web/app/desktop/tags/index.js
index a90e42211..6bbb774ee 100644
--- a/src/web/app/desktop/tags/index.js
+++ b/src/web/app/desktop/tags/index.js
@@ -41,7 +41,6 @@ require('./home-widgets/notifications.tag');
 require('./home-widgets/rss-reader.tag');
 require('./home-widgets/photo-stream.tag');
 require('./home-widgets/broadcast.tag');
-require('./stream-indicator.tag');
 require('./timeline.tag');
 require('./messaging/window.tag');
 require('./messaging/room-window.tag');
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index 9ef7a2504..2e3262fed 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -455,6 +455,7 @@
 					wait: false
 				});
 			});
+		};
 
 		this.cat = () => {
 			this.refs.text.value += getCat();
diff --git a/src/web/app/dev/tags/new-app-form.tag b/src/web/app/dev/tags/new-app-form.tag
index c75eec37d..e01be512f 100644
--- a/src/web/app/dev/tags/new-app-form.tag
+++ b/src/web/app/dev/tags/new-app-form.tag
@@ -180,64 +180,73 @@
 	<script>
 		this.mixin('api');
 
-		this.nid-state = null
+		this.nidState = null;
 
-		this.on-change-nid = () => {
-			nid = this.refs.nid.value
+		this.onChangeNid = () => {
+			const nid = this.refs.nid.value;
 
-			if nid == ''
-				this.nid-state = null
-				this.update();
-				return
+			if (nid == '') {
+				this.update({
+					nidState: null
+				});
+				return;
+			}
 
-			err = switch
-				| not nid.match /^[a-zA-Z0-9\-]+$/ => 'invalid-format' 
-				| nid.length < 3chars              => 'min-range' 
-				| nid.length > 30chars             => 'max-range' 
-				| _                                     => null
+			const err =
+				!nid.match(/^[a-zA-Z0-9\-]+$/) ? 'invalid-format' :
+				nid.length < 3                 ? 'min-range' :
+				nid.length > 30                ? 'max-range' :
+				null;
 
-			if err?
-				this.nid-state = err
-				this.update();
-			else
-				this.nid-state = 'wait' 
-				this.update();
+			if (err) {
+				this.update({
+					nidState: err
+				});
+				return;
+			}
 
-				this.api('app/name_id/available', {
-					name_id: nid
-				}).then((result) => {
-					if result.available
-						this.nid-state = 'ok' 
-					else
-						this.nid-state = 'unavailable' 
-					this.update();
-				.catch (err) =>
-					this.nid-state = 'error' 
-					this.update();
+			this.update({
+				nidState: 'wait'
+			});
+
+			this.api('app/name_id/available', {
+				name_id: nid
+			}).then(result => {
+				this.update({
+					nidState: result.available ? 'ok' : 'unavailable'
+				});
+			}).catch(err => {
+				this.update({
+					nidState: 'error'
+				});
+			});
+		};
 
 		this.onsubmit = () => {
-			name = this.refs.name.value
-			nid = this.refs.nid.value
-			description = this.refs.description.value
-			cb = this.refs.cb.value
-			permission = []
+			const name = this.refs.name.value;
+			const nid = this.refs.nid.value;
+			const description = this.refs.description.value;
+			const cb = this.refs.cb.value;
+			const permission = [];
 
-			this.refs.permission.query-selector-all 'input' .forEach (el) =>
-				if el.checked then permission.push el.value
+			this.refs.permission.querySelectorAll('input').forEach(el => {
+				if (el.checked) permission.push(el.value);
+			});
+
+			const locker = document.body.appendChild(document.createElement('mk-locker'));
 
-			locker = document.body.appendChild(document.createElement('mk-locker'));
- 
 			this.api('app/create', {
-				name: name
-				name_id: nid
-				description: description
-				callback_url: cb
-				permission: permission.join ',' 
+				name: name,
+				name_id: nid,
+				description: description,
+				callback_url: cb,
+				permission: permission.join(',')
 			}).then(() => {
-				location.href = '/apps'
-			.catch =>
-				alert 'アプリの作成に失敗しました。再度お試しください。'
-
-				locker.parentNode.removeChild locker
+				location.href = '/apps';
+			}).catch(() => {
+				alert('アプリの作成に失敗しました。再度お試しください。');
+				locker.parentNode.removeChild(locker);
+			});
+		};
 	</script>
 </mk-new-app-form>
diff --git a/src/web/app/dev/tags/pages/app.tag b/src/web/app/dev/tags/pages/app.tag
index e6cadab1b..b25e0d859 100644
--- a/src/web/app/dev/tags/pages/app.tag
+++ b/src/web/app/dev/tags/pages/app.tag
@@ -12,19 +12,21 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('api');
 
-		this.fetching = true
+		this.fetching = true;
 
 		this.on('mount', () => {
 			this.api('app/show', {
 				app_id: this.opts.app
-			}).then((app) => {
-				this.app = app
-				this.fetching = false
-				this.update();
+			}).then(app => {
+				this.update({
+					fetching: false,
+					app: app
+				});
+			});
+		});
 	</script>
 </mk-app-page>
diff --git a/src/web/app/dev/tags/pages/apps.tag b/src/web/app/dev/tags/pages/apps.tag
index c87141711..43db70fcf 100644
--- a/src/web/app/dev/tags/pages/apps.tag
+++ b/src/web/app/dev/tags/pages/apps.tag
@@ -13,18 +13,21 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
 		this.mixin('api');
 
-		this.fetching = true
+		this.fetching = true;
 
 		this.on('mount', () => {
-			this.api 'my/apps' 
-			}).then((apps) => {
+			this.api('my/apps').then(apps => {
 				this.fetching = false
 				this.apps = apps
-				this.update();
+				this.update({
+					fetching: false,
+					apps: apps
+				});
+			});
+		});
 	</script>
 </mk-apps-page>
diff --git a/src/web/app/dev/tags/pages/index.tag b/src/web/app/dev/tags/pages/index.tag
index ff2494212..f863876fa 100644
--- a/src/web/app/dev/tags/pages/index.tag
+++ b/src/web/app/dev/tags/pages/index.tag
@@ -2,10 +2,5 @@
 	<style>
 		:scope
 			display block
-
-			
-
-			
-
 	</style>
 </mk-index>
diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag
index 36c037d1a..707ec9478 100644
--- a/src/web/app/mobile/tags/drive.tag
+++ b/src/web/app/mobile/tags/drive.tag
@@ -3,7 +3,7 @@
 		<p onclick={ goRoot }><i class="fa fa-cloud"></i>ドライブ</p>
 		<virtual each={ folder in hierarchyFolders }>
 			<span><i class="fa fa-angle-right"></i></span>
-			<p onclick={ _move }>{ folder.name }</p>
+			<p onclick={ move }>{ folder.name }</p>
 		</virtual>
 		<virtual if={ folder != null }>
 			<span><i class="fa fa-angle-right"></i></span>
@@ -14,7 +14,7 @@
 			<p>{ file.name }</p>
 		</virtual>
 	</nav>
-	<div class="browser { loading: loading }" if={ file == null }>
+	<div class="browser { loading: fetching }" if={ file == null }>
 		<div class="folders" if={ folders.length > 0 }>
 			<virtual each={ folder in folders }>
 				<mk-drive-folder folder={ folder }></mk-drive-folder>
@@ -27,11 +27,11 @@
 			</virtual>
 			<p if={ moreFiles }>もっと読み込む</p>
 		</div>
-		<div class="empty" if={ files.length == 0 && folders.length == 0 && !loading }>
+		<div class="empty" if={ files.length == 0 && folders.length == 0 && !fetching }>
 			<p if={ !folder == null }>ドライブには何もありません。</p>
 			<p if={ folder != null }>このフォルダーは空です</p>
 		</div>
-		<div class="loading" if={ loading }>
+		<div class="loading" if={ fetching }>
 			<div class="spinner">
 				<div class="dot1"></div>
 				<div class="dot2"></div>
@@ -131,247 +131,263 @@
 		this.mixin('api');
 		this.mixin('stream');
 
-		this.files = []
-		this.folders = []
-		this.hierarchyFolders = []
-		this.selected-files = []
+		this.files = [];
+		this.folders = [];
+		this.hierarchyFolders = [];
+		this.selectedFiles = [];
 
 		// 現在の階層(フォルダ)
 		// * null でルートを表す
-		this.folder = null
+		this.folder = null;
 
-		this.file = null
+		this.file = null;
 
-		this.is-select-mode = this.opts.select? and this.opts.select
-		this.multiple = if this.opts.multiple? then this.opts.multiple else false
+		this.isSelectMode = this.opts.select;
+		this.multiple =this.opts.multiple;
 
 		this.on('mount', () => {
-			this.stream.on 'drive_file_created' this.onStreamDriveFileCreated
-			this.stream.on 'drive_file_updated' this.onStreamDriveFileUpdated
-			this.stream.on 'drive_folder_created' this.onStreamDriveFolderCreated
-			this.stream.on 'drive_folder_updated' this.onStreamDriveFolderUpdated
+			this.stream.on('drive_file_created', this.onStreamDriveFileCreated);
+			this.stream.on('drive_file_updated', this.onStreamDriveFileUpdated);
+			this.stream.on('drive_folder_created', this.onStreamDriveFolderCreated);
+			this.stream.on('drive_folder_updated', this.onStreamDriveFolderUpdated);
 
 			// Riotのバグでnullを渡しても""になる
 			// https://github.com/riot/riot/issues/2080
-			#if this.opts.folder?
-			if this.opts.folder? and this.opts.folder != ''
-				@cd this.opts.folder, true
-			else if this.opts.file? and this.opts.file != ''
-				@cf this.opts.file, true
-			else
+			//if (this.opts.folder)
+			//if (this.opts.file)
+			if (this.opts.folder && this.opts.folder != '') {
+				this.cd(this.opts.folder, true);
+			} else if (this.opts.file && this.opts.file != '') {
+				this.cf(this.opts.file, true);
+			} else {
 				this.load();
+			}
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'drive_file_created' this.onStreamDriveFileCreated
-			this.stream.off 'drive_file_updated' this.onStreamDriveFileUpdated
-			this.stream.off 'drive_folder_created' this.onStreamDriveFolderCreated
-			this.stream.off 'drive_folder_updated' this.onStreamDriveFolderUpdated
+			this.stream.off('drive_file_created', this.onStreamDriveFileCreated);
+			this.stream.off('drive_file_updated', this.onStreamDriveFileUpdated);
+			this.stream.off('drive_folder_created', this.onStreamDriveFolderCreated);
+			this.stream.off('drive_folder_updated', this.onStreamDriveFolderUpdated);
+		});
 
-		this.onStreamDriveFileCreated = (file) => {
-			this.addFile file, true
+		this.onStreamDriveFileCreated = file => {
+			this.addFile(file, true);
+		};
 
-		this.onStreamDriveFileUpdated = (file) => {
-			current = if this.folder? then this.folder.id else null
-			if current != file.folder_id
-				@remove-file file
-			else
-				this.addFile file, true
+		this.onStreamDriveFileUpdated = file => {
+			const current = this.folder ? this.folder.id : null;
+			if (current != file.folder_id) {
+				this.removeFile(file);
+			} else {
+				this.addFile(file, true);
+			}
+		};
 
-		this.onStreamDriveFolderCreated = (folder) => {
-			this.addFolder folder, true
+		this.onStreamDriveFolderCreated = folder => {
+			this.addFolder(folder, true);
+		};
 
-		this.onStreamDriveFolderUpdated = (folder) => {
-			current = if this.folder? then this.folder.id else null
-			if current != folder.parent_id
-				this.removeFolder folder
-			else
-				this.addFolder folder, true
+		this.onStreamDriveFolderUpdated = folder => {
+			const current = this.folder ? this.folder.id : null;
+			if (current != folder.parent_id) {
+				this.removeFolder(folder);
+			} else {
+				this.addFolder(folder, true);
+			}
+		};
 
-		@_move = (ev) =>
-			this.move ev.item.folder
+		this.move = ev => {
+			this.move(ev.item.folder);
+		};
 
-		this.move = (target-folder) => {
-			@cd target-folder
+		this.cd = (target, silent = false) => {
+			this.file = null;
 
-		this.cd = (target-folder, silent = false) => {
-			this.file = null
+			if (target == null) {
+				this.goRoot();
+				return;
+			} else if (typeof target == 'object') target = target.id;
 
-			if target-folder? and typeof target-folder == 'object' 
-				target-folder = target-folder.id
-
-			if target-folder == null
-				@go-root!
-				return
-
-			this.loading = true
-			this.update();
+			this.update({
+				fetching: true
+			});
 
 			this.api('drive/folders/show', {
-				folder_id: target-folder
-			}).then((folder) => {
-				this.folder = folder
-				this.hierarchyFolders = []
+				folder_id: target
+			}).then(folder => {
+				this.folder = folder;
+				this.hierarchyFolders = [];
 
-				x = (f) =>
-					@hierarchyFolders.unshift f
-					if f.parent?
-						x f.parent
-
-				if folder.parent?
-					x folder.parent
+				if (folder.parent) dive(folder.parent);
 
 				this.update();
-				this.trigger 'open-folder' this.folder, silent
+				this.trigger('open-folder', this.folder, silent);
 				this.load();
-			.catch (err, text-status) ->
-				console.error err
+			});
+		};
 
-		this.add-folder = (folder, unshift = false) => {
-			current = if this.folder? then this.folder.id else null
-			if current != folder.parent_id
-				return
+		this.addFolder = (folder, unshift = false) => {
+			const current = this.folder ? this.folder.id : null;
+			// 追加しようとしているフォルダが、今居る階層とは違う階層のものだったら中断
+			if (current != folder.parent_id) return;
 
-			if (this.folders.some (f) => f.id == folder.id)
-				return
+			// 追加しようとしているフォルダを既に所有してたら中断
+			if (this.folders.some(f => f.id == folder.id)) return;
 
-			if unshift
-				this.folders.unshift folder
-			else
-				this.folders.push folder
+			if (unshift) {
+				this.folders.unshift(folder);
+			} else {
+				this.folders.push(folder);
+			}
 
 			this.update();
+		};
 
-		this.add-file = (file, unshift = false) => {
-			current = if this.folder? then this.folder.id else null
-			if current != file.folder_id
-				return
+		this.addFile = (file, unshift = false) => {
+			const current = this.folder ? this.folder.id : null;
+			// 追加しようとしているファイルが、今居る階層とは違う階層のものだったら中断
+			if (current != file.folder_id) return;
 
-			if (this.files.some (f) => f.id == file.id)
-				exist = (this.files.map (f) -> f.id).index-of file.id
-				this.files[exist] = file
+			if (this.files.some(f => f.id == file.id)) {
+				const exist = this.files.map(f => f.id).indexOf(file.id);
+				this.files[exist] = file;
 				this.update();
-				return
+				return;
+			}
 
-			if unshift
-				this.files.unshift file
-			else
-				this.files.push file
+			if (unshift) {
+				this.files.unshift(file);
+			} else {
+				this.files.push(file);
+			}
 
 			this.update();
+		};
 
-		this.remove-folder = (folder) => {
-			if typeof folder == 'object' 
-				folder = folder.id
-			this.folders = this.folders.filter (f) -> f.id != folder
+		this.removeFolder = folder => {
+			if (typeof folder == 'object') folder = folder.id;
+			this.folders = this.folders.filter(f => f.id != folder);
 			this.update();
+		};
 
-		this.remove-file = (file) => {
-			if typeof file == 'object' 
-				file = file.id
-			this.files = this.files.filter (f) -> f.id != file
+		this.removeFile = file => {
+			if (typeof file == 'object') file = file.id;
+			this.files = this.files.filter(f => f.id != file);
 			this.update();
+		};
 
-		this.go-root = () => {
-			if this.folder != null or this.file != null
-				this.file = null
-				this.folder = null
-				this.hierarchyFolders = []
-				this.update();
+		this.goRoot = () => {
+			if (this.folder || this.file) {
+				this.update({
+					file: null,
+					folder: null,
+					hierarchyFolders: []
+				});
 				this.trigger('move-root');
 				this.load();
+			}
+		};
 
 		this.load = () => {
-			this.folders = []
-			this.files = []
-			this.more-folders = false
-			this.more-files = false
-			this.loading = true
-			this.update();
+			this.update({
+				folders: [],
+				files: [],
+				moreFolders: false,
+				moreFiles: false,
+				fetching: true
+			});
 
 			this.trigger('begin-load');
 
-			load-folders = null
-			load-files = null
+			let fetchedFolders = null;
+			let fetchedFiles = null;
 
-			folders-max = 20
-			files-max = 20
+			const foldersMax = 20;
+			const filesMax = 20;
 
 			// フォルダ一覧取得
 			this.api('drive/folders', {
-				folder_id: if this.folder? then this.folder.id else null
-				limit: folders-max + 1
-			}).then((folders) => {
-				if folders.length == folders-max + 1
-					this.more-folders = true
-					folders.pop!
-				load-folders := folders
-				complete!
-			.catch (err, text-status) =>
-				console.error err
+				folder_id: this.folder ? this.folder.id : null,
+				limit: foldersMax + 1
+			}).then(folders => {
+				if (folders.length == foldersMax + 1) {
+					this.moreFolders = true;
+					folders.pop();
+				}
+				fetchedFolders = folders;
+				complete();
+			});
 
 			// ファイル一覧取得
 			this.api('drive/files', {
-				folder_id: if this.folder? then this.folder.id else null
-				limit: files-max + 1
-			}).then((files) => {
-				if files.length == files-max + 1
-					this.more-files = true
-					files.pop!
-				load-files := files
-				complete!
-			.catch (err, text-status) =>
-				console.error err
-
-			flag = false
-			complete = =>
-				if flag
-					load-folders.forEach (folder) =>
-						this.addFolder folder
-					load-files.forEach (file) =>
-						this.addFile file
-					this.loading = false
-					this.update();
+				folder_id: this.folder ? this.folder.id : null,
+				limit: filesMax + 1
+			}).then(files => {
+				if (files.length == filesMax + 1) {
+					this.moreFiles = true;
+					files.pop();
+				}
+				fetchedFiles = files;
+				complete();
+			});
 
+			let flag = false;
+			complete = () => {
+				if (flag) {
+					fetchedFolders.forEach(folder => this.addFolder);
+					fetchedFiles.forEach(file => this.addFile);
+					this.update({
+						fetching: false
+					});
+					// 一連の読み込みが完了したイベントを発行
 					this.trigger('loaded');
-				else
-					flag := true
+				} else {
+					flag = true;
+					// 一連の読み込みが半分完了したイベントを発行
 					this.trigger('load-mid');
+				}
+			};
+		};
 
-		this.choose-file = (file) => {
-			if @is-select-mode
-				exist = @selected-files.some (f) => f.id == file.id
-				if exist
-					this.selected-files = (@selected-files.filter (f) => { f.id != file.id)
-				else
-					@selected-files.push file
+		this.chooseFile = file => {
+			if (this.isSelectMode) {
+				if (this.selectedFiles.some(f => f.id == file.id)) {
+					this.selectedFiles = this.selectedFiles.filter(f => f.id != file.id);
+				} else {
+					this.selectedFiles.push(file);
+				}
 				this.update();
-				this.trigger 'change-selected' @selected-files
-			else
-				@cf file
+				this.trigger('change-selected', this.selectedFiles);
+			} else {
+				this.cf(file);
+			}
+		};
 
 		this.cf = (file, silent = false) => {
-			if typeof file == 'object' 
-				file = file.id
+			if (typeof file == 'object') file = file.id;
 
-			this.loading = true
-			this.update();
+			this.update({
+				fetching: true
+			});
 
 			this.api('drive/files/show', {
 				file_id: file
-			}).then((file) => {
-				this.file = file
-				this.folder = null
-				this.hierarchyFolders = []
+			}).then(file => {
+				this.file = file;
+				this.folder = null;
+				this.hierarchyFolders = [];
 
-				x = (f) =>
-					@hierarchyFolders.unshift f
-					if f.parent?
-						x f.parent
-
-				if file.folder?
-					x file.folder
+				if (file.folder) dive(file.folder);
 
 				this.update();
-				this.trigger 'open-file' this.file, silent
+				this.trigger('open-file', this.file, silent);
+			});
+		};
+
+		const dive = folder => {
+			this.hierarchyFolders.unshift(folder);
+			if (folder.parent) dive(folder.parent);
+		};
 	</script>
 </mk-drive>
diff --git a/src/web/app/mobile/tags/drive/file-viewer.tag b/src/web/app/mobile/tags/drive/file-viewer.tag
index e91a451c0..78a10b83b 100644
--- a/src/web/app/mobile/tags/drive/file-viewer.tag
+++ b/src/web/app/mobile/tags/drive/file-viewer.tag
@@ -185,17 +185,18 @@
 
 		this.mixin('api');
 
-		this.file = this.opts.file
-		this.kind = this.file.type.split '/' .0
+		this.file = this.opts.file;
+		this.kind = this.file.type.split('/')[0];
 
 		this.rename = () => {
-			name = window.prompt '名前を変更' this.file.name
-			if name? and name != '' and name != this.file.name
-				this.api('drive/files/update', {
-					file_id: this.file.id,
-					name: name
-				}).then(() => {
-					this.parent.cf this.file, true
-
+			const name = window.prompt('名前を変更', this.file.name);
+			if (name == null || name == '' || name == this.file.name) return;
+			this.api('drive/files/update', {
+				file_id: this.file.id,
+				name: name
+			}).then(() => {
+				this.parent.cf(this.file, true);
+			});
+		};
 	</script>
 </mk-drive-file-viewer>
diff --git a/src/web/app/mobile/tags/drive/file.tag b/src/web/app/mobile/tags/drive/file.tag
index 77b5b220a..f800fd69e 100644
--- a/src/web/app/mobile/tags/drive/file.tag
+++ b/src/web/app/mobile/tags/drive/file.tag
@@ -124,14 +124,16 @@
 	<script>
 		this.bytesToSize = require('../../../common/scripts/bytesToSize.js');
 
-		this.browser = this.parent
-		this.file = this.opts.file
-		this.is-selected = this.browser.selected-files.some (f) => f.id == this.file.id
+		this.browser = this.parent;
+		this.file = this.opts.file;
+		this.isSelected = this.browser.selectedFiles.some(f => f.id == this.file.id);
 
-		this.browser.on('change-selected', (selects) => {
-			this.is-selected = selects.some (f) => f.id == this.file.id
+		this.browser.on('change-selected', selections => {
+			this.isSelected = selections.some(f => f.id == this.file.id);
+		});
 
 		this.onclick = () => {
-			this.browser.choose-file this.file
+			this.browser.chooseFile(this.file);
+		};
 	</script>
 </mk-drive-file>
diff --git a/src/web/app/mobile/tags/drive/folder.tag b/src/web/app/mobile/tags/drive/folder.tag
index 4c4727a30..093e74292 100644
--- a/src/web/app/mobile/tags/drive/folder.tag
+++ b/src/web/app/mobile/tags/drive/folder.tag
@@ -37,10 +37,11 @@
 
 	</style>
 	<script>
-		this.browser = this.parent
-		this.folder = this.opts.folder
+		this.browser = this.parent;
+		this.folder = this.opts.folder;
 
 		this.onclick = () => {
-			this.browser.move this.folder
+			this.browser.move(this.folder);
+		};
 	</script>
 </mk-drive-folder>
diff --git a/src/web/app/mobile/tags/follow-button.tag b/src/web/app/mobile/tags/follow-button.tag
index 43fcc3499..ae6d19f59 100644
--- a/src/web/app/mobile/tags/follow-button.tag
+++ b/src/web/app/mobile/tags/follow-button.tag
@@ -52,54 +52,70 @@
 		this.mixin('is-promise');
 		this.mixin('stream');
 
-		this.user = null
-		this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
-		this.init = true
-		this.wait = false
+		this.user = null;
+		this.userPromise = this.isPromise(this.opts.user)
+			? this.opts.user
+			: Promise.resolve(this.opts.user);
+		this.init = true;
+		this.wait = false;
 
 		this.on('mount', () => {
-			this.user-promise}).then((user) => {
-				this.user = user
-				this.init = false
-				this.update();
-				this.stream.on 'follow' this.on-stream-follow
-				this.stream.on 'unfollow' this.on-stream-unfollow
+			this.userPromise.then(user => {
+				this.update({
+					init: false,
+					user: user
+				});
+				this.stream.on('follow', this.onStreamFollow);
+				this.stream.on('unfollow', this.onStreamUnfollow);
+			});
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'follow' this.on-stream-follow
-			this.stream.off 'unfollow' this.on-stream-unfollow
+			this.stream.off('follow', this.onStreamFollow);
+			this.stream.off('unfollow', this.onStreamUnfollow);
+		});
 
-		this.on-stream-follow = (user) => {
-			if user.id == this.user.id
-				this.user = user
-				this.update();
+		this.onStreamFollow = user => {
+			if (user.id == this.user.id) {
+				this.update({
+					user: user
+				});
+			}
+		};
 
-		this.on-stream-unfollow = (user) => {
-			if user.id == this.user.id
-				this.user = user
-				this.update();
+		this.onStreamUnfollow = user => {
+			if (user.id == this.user.id) {
+				this.update({
+					user: user
+				});
+			}
+		};
 
 		this.onclick = () => {
-			this.wait = true
-			if this.user.is_following
+			this.wait = true;
+			if (this.user.is_following) {
 				this.api('following/delete', {
 					user_id: this.user.id
 				}).then(() => {
-					this.user.is_following = false
-				.catch (err) ->
-					console.error err
+					this.user.is_following = false;
+				}).catch(err => {
+					console.error(err);
 				}).then(() => {
-					this.wait = false
+					this.wait = false;
 					this.update();
-			else
+				});
+			} else {
 				this.api('following/create', {
 					user_id: this.user.id
 				}).then(() => {
-					this.user.is_following = true
-				.catch (err) ->
-					console.error err
+					this.user.is_following = true;
+				}).catch(err => {
+					console.error(err);
 				}).then(() => {
-					this.wait = false
+					this.wait = false;
 					this.update();
+				});
+			}
+		};
 	</script>
 </mk-follow-button>
diff --git a/src/web/app/mobile/tags/images-viewer.tag b/src/web/app/mobile/tags/images-viewer.tag
index ad02850e3..f3724f21b 100644
--- a/src/web/app/mobile/tags/images-viewer.tag
+++ b/src/web/app/mobile/tags/images-viewer.tag
@@ -18,10 +18,11 @@
 
 	</style>
 	<script>
-		this.images = this.opts.images
-		this.image = @images.0
+		this.images = this.opts.images;
+		this.image = this.images[0];
 
 		this.click = () => {
-			window.open @image.url
+			window.open(this.image.url);
+		};
 	</script>
 </mk-images-viewer>
diff --git a/src/web/app/mobile/tags/index.js b/src/web/app/mobile/tags/index.js
index 2a8f2161c..dec2be332 100644
--- a/src/web/app/mobile/tags/index.js
+++ b/src/web/app/mobile/tags/index.js
@@ -1,7 +1,6 @@
 require('./ui.tag');
 require('./ui-header.tag');
 require('./ui-nav.tag');
-require('./stream-indicator.tag');
 require('./page/entrance.tag');
 require('./page/entrance/signin.tag');
 require('./page/entrance/signup.tag');
diff --git a/src/web/app/mobile/tags/notification-preview.tag b/src/web/app/mobile/tags/notification-preview.tag
index 800d1b434..b93b92d91 100644
--- a/src/web/app/mobile/tags/notification-preview.tag
+++ b/src/web/app/mobile/tags/notification-preview.tag
@@ -108,6 +108,6 @@
 	</style>
 	<script>
 		this.mixin('get-post-summary');
-		this.notification = this.opts.notification
+		this.notification = this.opts.notification;
 	</script>
 </mk-notification-preview>
diff --git a/src/web/app/mobile/tags/notification.tag b/src/web/app/mobile/tags/notification.tag
index 9cf61fe40..d32e6b40a 100644
--- a/src/web/app/mobile/tags/notification.tag
+++ b/src/web/app/mobile/tags/notification.tag
@@ -168,6 +168,6 @@
 	</style>
 	<script>
 		this.mixin('get-post-summary');
-		this.notification = this.opts.notification
+		this.notification = this.opts.notification;
 	</script>
 </mk-notification>
diff --git a/src/web/app/mobile/tags/notifications.tag b/src/web/app/mobile/tags/notifications.tag
index 9fb695a43..e73877266 100644
--- a/src/web/app/mobile/tags/notifications.tag
+++ b/src/web/app/mobile/tags/notifications.tag
@@ -61,33 +61,36 @@
 		this.mixin('stream');
 		this.mixin('get-post-summary');
 
-		this.notifications = []
-		this.loading = true
+		this.notifications = [];
+		this.loading = true;
 
 		this.on('mount', () => {
-			this.api 'i/notifications' 
-			}).then((notifications) => {
-				this.notifications = notifications
-				this.loading = false
-				this.update();
-				this.trigger('loaded');
-			.catch (err, text-status) ->
-				console.error err
+			this.api('i/notifications').then(notifications => {
+				this.update({
+					loading: false,
+					notifications: notifications
+				});
+			});
 
-			this.stream.on 'notification' this.on-notification
+			this.stream.on('notification', this.onNotification);
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'notification' this.on-notification
+			this.stream.off('notification', this.onNotification);
+		});
 
-		this.on-notification = (notification) => {
-			@notifications.unshift notification
+		this.onNotification = notification => {
+			this.notifications.unshift(notification);
 			this.update();
+		};
 
 		this.on('update', () => {
-			@notifications.forEach (notification) =>
-				date = (new Date notification.created_at).getDate()
-				month = (new Date notification.created_at).getMonth() + 1
-				notification._date = date
-				notification._datetext = month + '月 ' + date + '日'
+			this.notifications.forEach(notification => {
+				const date = new Date(notification.created_at).getDate();
+				const month = new Date(notification.created_at).getMonth() + 1;
+				notification._date = date;
+				notification._datetext = `${month}月 ${date}日`;
+			});
+		});
 	</script>
 </mk-notifications>
diff --git a/src/web/app/mobile/tags/notify.tag b/src/web/app/mobile/tags/notify.tag
index 3003528fe..c97e70696 100644
--- a/src/web/app/mobile/tags/notify.tag
+++ b/src/web/app/mobile/tags/notify.tag
@@ -18,21 +18,21 @@
 	<script>
 		this.on('mount', () => {
 			Velocity(this.root, {
-				bottom: '0px' 
+				bottom: '0px'
 			}, {
-				duration: 500ms
-				easing: 'ease-out' 
-			}
+				duration: 500,
+				easing: 'ease-out'
+			});
 
-			setTimeout =>
+			setTimeout(() => {
 				Velocity(this.root, {
-					bottom: '-64px' 
+					bottom: '-64px'
 				}, {
-					duration: 500ms
-					easing: 'ease-out' 
-					complete: =>
-						this.unmount();
-				}
-			, 6000ms
+					duration: 500,
+					easing: 'ease-out',
+					complete: () => this.unmount()
+				});
+			}, 6000);
+		});
 	</script>
 </mk-notify>
diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag
index 2b4bef1da..e8149e098 100644
--- a/src/web/app/mobile/tags/post-detail.tag
+++ b/src/web/app/mobile/tags/post-detail.tag
@@ -342,89 +342,111 @@
 		this.on('mount', () => {
 			this.api('posts/show', {
 				post_id: this.opts.post
-			}).then((post) => {
-				this.post = post
-				this.is-repost = this.post.repost?
-				this.p = if @is-repost then this.post.repost else this.post
-				this.summary = @get-post-summary this.p
+			}).then(post => {
+				const isRepost = post.repost != null;
+				const p = isRepost ? post.repost : post;
+				this.update({
+					fetching: false,
+					post: post,
+					isRepost: isRepost,
+					p: p
+				});
+
 				this.trigger('loaded');
-				this.fetching = false
-				this.update();
 
-				if this.p.text?
-					tokens = @analyze this.p.text
-					this.refs.text.innerHTML = @compile tokens
+				if (this.p.text) {
+					const tokens = this.analyze(this.p.text);
 
-					this.refs.text.children.forEach (e) =>
-						if e.tag-name == 'MK-URL' 
-							riot.mount e
+					this.refs.text.innerHTML = this.compile(tokens);
+
+					this.refs.text.children.forEach(e => {
+						if (e.tagName == 'MK-URL') riot.mount(e);
+					});
 
 					// URLをプレビュー
 					tokens
-						.filter (t) -> t.type == 'link' 
-						.map (t) =>
-							this.preview = this.refs.text.appendChild(document.createElement('mk-url-preview'));
- 							riot.mount this.preview, do
-								url: t.content
+					.filter(t => t.type == 'link')
+					.map(t => {
+						riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
+							url: t.content
+						});
+					});
+				}
 
 				// Get likes
 				this.api('posts/likes', {
-					post_id: this.p.id
+					post_id: this.p.id,
 					limit: 8
-				}).then((likes) => {
-					this.likes = likes
-					this.update();
+				}).then(likes => {
+					this.update({
+						likes: likes
+					});
+				});
 
 				// Get reposts
 				this.api('posts/reposts', {
-					post_id: this.p.id
+					post_id: this.p.id,
 					limit: 8
-				}).then((reposts) => {
-					this.reposts = reposts
-					this.update();
+				}).then(reposts => {
+					this.update({
+						reposts: reposts
+					});
+				});
 
 				// Get replies
 				this.api('posts/replies', {
-					post_id: this.p.id
+					post_id: this.p.id,
 					limit: 8
-				}).then((replies) => {
-					this.replies = replies
-					this.update();
+				}).then(replies => {
+					this.update({
+						replies: replies
+					});
+				});
+			});
+		});
 
 		this.reply = () => {
-			this.openPostForm do
+			riot.mount(document.body.appendChild(document.createElement('mk-post-form-window')), {
 				reply: this.p
+			});
+		};
 
 		this.repost = () => {
-			text = window.prompt '「' + @summary + '」をRepost'
-			if text?
-				this.api('posts/create', {
-					repost_id: this.p.id
-					text: if text == '' then undefined else text
+			riot.mount(document.body.appendChild(document.createElement('mk-repost-form-window')), {
+				post: this.p
+			});
+		};
 
 		this.like = () => {
-			if this.p.is_liked
+			if (this.p.is_liked) {
 				this.api('posts/likes/delete', {
 					post_id: this.p.id
 				}).then(() => {
-					this.p.is_liked = false
+					this.p.is_liked = false;
 					this.update();
-			else
+				});
+			} else {
 				this.api('posts/likes/create', {
 					post_id: this.p.id
 				}).then(() => {
-					this.p.is_liked = true
+					this.p.is_liked = true;
 					this.update();
+				});
+			}
+		};
 
-		this.load-context = () => {
-			this.loading-context = true
+		this.loadContext = () => {
+			this.loadingContext = true;
 
-			// Get context
+			// Fetch context
 			this.api('posts/context', {
 				post_id: this.p.reply_to_id
-			}).then((context) => {
-				this.context = context.reverse!
-				this.loading-context = false
-				this.update();
+			}).then(context => {
+				this.update({
+					loadContext: false,
+					content: context.reverse()
+				});
+			});
+		};
 	</script>
 </mk-post-detail>
diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag
index 27c6c005c..397475e3f 100644
--- a/src/web/app/mobile/tags/post-form.tag
+++ b/src/web/app/mobile/tags/post-form.tag
@@ -10,7 +10,7 @@
 	</header>
 	<div class="form">
 		<mk-post-preview if={ opts.reply } post={ opts.reply }></mk-post-preview>
-		<textarea ref="text" disabled={ wait } oninput={ update } onkeypress={ onkeypress } onpaste={ onpaste } placeholder={ opts.reply ? 'この投稿への返信...' : 'いまどうしてる?' }></textarea>
+		<textarea ref="text" disabled={ wait } oninput={ update } onkeydown={ onkeydown } onpaste={ onpaste } placeholder={ opts.reply ? 'この投稿への返信...' : 'いまどうしてる?' }></textarea>
 		<div class="attaches" if={ files.length != 0 }>
 			<ul class="files" ref="attaches">
 				<li class="file" each={ files }>
@@ -182,103 +182,111 @@
 
 	</style>
 	<script>
-		get-cat = require('../../common/scripts/get-cat');
+		getCat = require('../../common/scripts/get-cat');
 
 		this.mixin('api');
 
-		this.wait = false
-		this.uploadings = []
-		this.files = []
-		this.poll = false
+		this.wait = false;
+		this.uploadings = [];
+		this.files = [];
+		this.poll = false;
 
 		this.on('mount', () => {
-			this.refs.uploader.on('uploaded', (file) => {
-				this.addFile file
+			this.refs.uploader.on('uploaded', file => {
+				this.addFile(file);
+			});
 
-			this.refs.uploader.on('change-uploads', (uploads) => {
-				this.trigger 'change-uploading-files' uploads
+			this.refs.uploader.on('change-uploads', uploads => {
+				this.trigger('change-uploading-files', uploads);
+			});
 
 			this.refs.text.focus();
+		});
 
-		this.onkeypress = (e) => {
-			if (e.char-code == 10 || e.char-code == 13) && e.ctrlKey
-				this.post!
-			else
-				return true
+		this.onkeydown = e => {
+			if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.meta-key)) this.post();
+		};
 
-		this.onpaste = (e) => {
-			data = e.clipboardData
-			items = data.items
-			for i from 0 to items.length - 1
-				item = items[i]
-				switch (item.kind)
-					| 'file' =>
-						@upload item.getAsFile();
-			return true
+		this.onpaste = e => {
+			e.clipboardData.items.forEach(item => {
+				if (item.kind == 'file') {
+					this.upload(item.getAsFile());
+				}
+			});
+		};
 
-		this.select-file = () => {
+		this.selectFile = () => {
 			this.refs.file.click();
+		};
 
-		this.select-file-from-drive = () => {
-			browser = document.body.appendChild(document.createElement('mk-drive-selector'));
- 			browser = riot.mount browser, do
+		this.selectFileFromDrive = () => {
+			const i = riot.mount(document.body.appendChild(document.createElement('mk-drive-selector')), {
 				multiple: true
-			.0
-			browser.on('selected', (files) => {
-				files.forEach this.addFile
+			})[0];
+			i.one('selected', files => {
+				files.forEach(this.addFile);
+			});
+		};
 
-		this.change-file = () => {
-			files = this.refs.file.files
-			for i from 0 to files.length - 1
-				file = files.item i
-				@upload file
+		this.changeFile = () => {
+			this.refs.file.files.forEach(this.upload);
+		};
 
-		this.upload = (file) => {
-			this.refs.uploader.upload file
+		this.upload = file => {
+			this.refs.uploader.upload(file);
+		};
 
-		this.add-file = (file) => {
-			file._remove = =>
-				this.files = this.files.filter (x) -> x.id != file.id
-				this.trigger 'change-files' this.files
+		this.addFile = file => {
+			file._remove = () => {
+				this.files = this.files.filter(x => x.id != file.id);
+				this.trigger('change-files', this.files);
 				this.update();
+			};
 
-			this.files.push file
-			this.trigger 'change-files' this.files
+			this.files.push(file);
+			this.trigger('change-files', this.files);
 			this.update();
+		};
 
-		this.add-poll = () => {
-			this.poll = true
+		this.addPoll = () => {
+			this.poll = true;
+		};
 
-		this.on-poll-destroyed = () => {
-			@update do
+		this.onPollDestroyed = () => {
+			this.update({
 				poll: false
+			});
+		};
 
 		this.post = () => {
-			this.wait = true
+			this.wait = true;
 
-			files = if this.files? and this.files.length > 0
-				then this.files.map (f) -> f.id
-				else undefined
+			const files = this.files && this.files.length > 0
+				? this.files.map(f => f.id)
+				: undefined;
 
 			this.api('posts/create', {
-				text: this.refs.text.value
-				media_ids: files
-				reply_to_id: if this.opts.reply? then this.opts.reply.id else undefined
-				poll: if this.poll then this.refs.poll.get! else undefined
-			}).then((data) => {
+				text: this.refs.text.value,
+				media_ids: files,
+				reply_to_id: this.inReplyToPost ? this.inReplyToPost.id : undefined,
+				poll: this.poll ? this.refs.poll.get() : undefined
+			}).then(data => {
 				this.trigger('post');
 				this.unmount();
-			.catch (err) =>
-				console.error err
-				#this.opts.ui.trigger 'notification' 'Error!'
-				this.wait = false
-				this.update();
+			}).catch(err => {
+				this.update({
+					wait: false
+				});
+			});
+		};
 
 		this.cancel = () => {
 			this.trigger('cancel');
 			this.unmount();
+		};
 
 		this.cat = () => {
-			this.refs.text.value = this.refs.text.value + get-cat!
+			this.refs.text.value += getCat();
+		};
 	</script>
 </mk-post-form>
diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag
index 2dbb162d7..b0efe1463 100644
--- a/src/web/app/mobile/tags/search-posts.tag
+++ b/src/web/app/mobile/tags/search-posts.tag
@@ -15,18 +15,22 @@
 		this.query = this.opts.query;
 		this.withMedia = this.opts.withMedia;
 
-		this.init = new Promise (res, rej) =>
+		this.init = new Promise((res, rej) => {
 			this.api('posts/search', {
 				query: this.query
 			}).then(posts => {
-				res posts
+				res(posts);
 				this.trigger('loaded');
+			});
+		});
 
 		this.more = () => {
 			this.offset += this.max;
 			this.api('posts/search', {
-				query: this.query
-				max: this.max
+				query: this.query,
+				max: this.max,
 				offset: this.offset
+			});
+		};
 	</script>
 </mk-search-posts>
diff --git a/src/web/app/mobile/tags/search.tag b/src/web/app/mobile/tags/search.tag
index ab7ba4fd2..831e5a3e3 100644
--- a/src/web/app/mobile/tags/search.tag
+++ b/src/web/app/mobile/tags/search.tag
@@ -3,13 +3,14 @@
 	<style>
 		:scope
 			display block
-
 	</style>
 	<script>
-		this.query = this.opts.query
+		this.query = this.opts.query;
 
 		this.on('mount', () => {
 			this.refs.posts.on('loaded', () => {
 				this.trigger('loaded');
+			});
+		});
 	</script>
 </mk-search>
diff --git a/src/web/app/mobile/tags/stream-indicator.tag b/src/web/app/mobile/tags/stream-indicator.tag
deleted file mode 100644
index 9ca311c47..000000000
--- a/src/web/app/mobile/tags/stream-indicator.tag
+++ /dev/null
@@ -1,54 +0,0 @@
-<mk-stream-indicator>
-	<p if={ state == 'initializing' }><i class="fa fa-spinner fa-spin"></i><span>接続中
-			<mk-ellipsis></mk-ellipsis></span></p>
-	<p if={ state == 'reconnecting' }><i class="fa fa-spinner fa-spin"></i><span>切断されました 接続中
-			<mk-ellipsis></mk-ellipsis></span></p>
-	<p if={ state == 'connected' }><i class="fa fa-check"></i><span>接続完了</span></p>
-	<style>
-		:scope
-			display block
-			pointer-events none
-			position fixed
-			z-index 16384
-			bottom 8px
-			right 8px
-			margin 0
-			padding 6px 12px
-			font-size 0.9em
-			color #fff
-			background rgba(0, 0, 0, 0.8)
-
-			> p
-				display block
-				margin 0
-
-				> i
-					margin-right 0.25em
-
-	</style>
-	<script>
-		this.mixin('stream');
-
-		this.on('before-mount', () => {
-			this.state = this.getStreamState();
-
-			if this.state == 'connected' 
-				this.root.style.opacity = 0
-
-		this.stream-state-ev.on('connected', () => {
-			this.state = this.getStreamState();
-			this.update();
-			setTimeout =>
-				Velocity(this.root, {
-					opacity: 0
-				} 200ms 'linear' 
-			, 1000ms
-
-		this.stream-state-ev.on('closed', () => {
-			this.state = this.getStreamState();
-			this.update();
-			Velocity(this.root, {
-				opacity: 1
-			} 0ms
-	</script>
-</mk-stream-indicator>
diff --git a/src/web/app/mobile/tags/sub-post-content.tag b/src/web/app/mobile/tags/sub-post-content.tag
index a5af90cc7..5ff01c502 100644
--- a/src/web/app/mobile/tags/sub-post-content.tag
+++ b/src/web/app/mobile/tags/sub-post-content.tag
@@ -30,15 +30,17 @@
 	<script>
 		this.mixin('text');
 
-		this.post = this.opts.post
+		this.post = this.opts.post;
 
 		this.on('mount', () => {
-			if this.post.text?
-				tokens = @analyze this.post.text
-				this.refs.text.innerHTML = @compile tokens, false
+			if (this.post.text) {
+				const tokens = this.analyze(this.post.text);
+				this.refs.text.innerHTML = this.compile(tokens, false);
 
-				this.refs.text.children.forEach (e) =>
-					if e.tag-name == 'MK-URL' 
-						riot.mount e
+				this.refs.text.children.forEach(e => {
+					if (e.tagName == 'MK-URL') riot.mount(e);
+				});
+			}
+		});
 	</script>
 </mk-sub-post-content>
diff --git a/src/web/app/mobile/tags/timeline-post.tag b/src/web/app/mobile/tags/timeline-post.tag
index a19fca7fc..0a6db9a92 100644
--- a/src/web/app/mobile/tags/timeline-post.tag
+++ b/src/web/app/mobile/tags/timeline-post.tag
@@ -344,7 +344,7 @@
 		};
 
 		this.like = () => {
-			if (this.p.is_liked)
+			if (this.p.is_liked) {
 				this.api('posts/likes/delete', {
 					post_id: this.p.id
 				}).then(() => {
diff --git a/src/web/app/mobile/tags/ui-header.tag b/src/web/app/mobile/tags/ui-header.tag
index 405db1897..30259ba91 100644
--- a/src/web/app/mobile/tags/ui-header.tag
+++ b/src/web/app/mobile/tags/ui-header.tag
@@ -13,7 +13,7 @@
 			$height = 48px
 
 			display block
-			position fixed
+			position sticky
 			top 0
 			z-index 1024
 			width 100%
@@ -91,10 +91,6 @@
 		this.mixin('ui');
 		this.mixin('open-post-form');
 
-		this.on('mount', () => {
-			this.opts.ready();
-		});
-
 		this.ui.on('title', title => {
 			if (this.refs.title) this.refs.title.innerHTML = title;
 		});
diff --git a/src/web/app/mobile/tags/ui-nav.tag b/src/web/app/mobile/tags/ui-nav.tag
index d8769d9c0..23d07efdc 100644
--- a/src/web/app/mobile/tags/ui-nav.tag
+++ b/src/web/app/mobile/tags/ui-nav.tag
@@ -120,12 +120,10 @@
 		this.mixin('i');
 		this.mixin('page');
 
-		this.on('mount', () => {
-			this.opts.ready!
-
 		this.search = () => {
-			query = window.prompt '検索' 
-			if query? and query != ''
-				this.page '/search:' + query
+			const query = window.prompt('検索');
+			if (query == null || query == '') return;
+			this.page('/search:' + query);
+		};
 	</script>
 </mk-ui-nav>
diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag
index ca6ac3f55..3b3c6823d 100644
--- a/src/web/app/mobile/tags/ui.tag
+++ b/src/web/app/mobile/tags/ui.tag
@@ -1,7 +1,7 @@
 <mk-ui>
 	<div class="global" ref="global">
-		<mk-ui-header ref="header" ready={ ready }></mk-ui-header>
-		<mk-ui-nav ref="nav" ready={ ready }></mk-ui-nav>
+		<mk-ui-header ref="header"></mk-ui-header>
+		<mk-ui-nav ref="nav"></mk-ui-nav>
 		<div class="content" ref="main"><yield /></div>
 	</div>
 	<mk-stream-indicator></mk-stream-indicator>
@@ -16,36 +16,25 @@
 	<script>
 		this.mixin('stream');
 
-		this.ready-count = 0
-		this.is-drawer-opening = false
-
-		#this.ui.on('notification', (text) => {
-		// alert text
+		this.isDrawerOpening = false;
 
 		this.on('mount', () => {
-			this.stream.on 'notification' this.on-stream-notification
-			@ready!
+			this.stream.on('notification', this.onStreamNotification);
+		});
 
 		this.on('unmount', () => {
-			this.stream.off 'notification' this.on-stream-notification
+			this.stream.off('notification', this.onStreamNotification);
+		});
 
-		this.ready = () => {
-			@ready-count++
+		this.toggleDrawer = () => {
+			this.isDrawerOpening = !this.isDrawerOpening;
+			this.refs.nav.root.style.display = this.isDrawerOpening ? 'block' : 'none';
+		};
 
-			if @ready-count == 2
-				@init-view-position!
-
-		this.init-view-position = () => {
-			top = this.refs.header.root.offset-height
-			this.refs.main.style.padding-top = top + 'px' 
-
-		this.toggle-drawer = () => {
-			this.is-drawer-opening = !@is-drawer-opening
-			this.refs.nav.root.style.display = if @is-drawer-opening then 'block' else 'none' 
-
-		this.on-stream-notification = (notification) => {
-			el = document.body.appendChild(document.createElement('mk-notify'));
- 			riot.mount el, do
+		this.onStreamNotification = notification => {
+			riot.mount(document.body.appendChild(document.createElement('mk-notify')), {
 				notification: notification
+			});
+		};
 	</script>
 </mk-ui>
diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag
index eecf09cab..3a1fc1d4b 100644
--- a/src/web/app/mobile/tags/user-followers.tag
+++ b/src/web/app/mobile/tags/user-followers.tag
@@ -8,18 +8,21 @@
 	<script>
 		this.mixin('api');
 
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.fetch = (iknow, limit, cursor, cb) => {
 			this.api('users/followers', {
-				user_id: this.user.id
-				iknow: iknow
-				limit: limit
-				cursor: if cursor? then cursor else undefined
-			.then cb
+				user_id: this.user.id,
+				iknow: iknow,
+				limit: limit,
+				cursor: cursor ? cursor : undefined
+			}).then(cb);
+		};
 
 		this.on('mount', () => {
 			this.refs.list.on('loaded', () => {
 				this.trigger('loaded');
+			});
+		};
 	</script>
 </mk-user-followers>
diff --git a/src/web/app/mobile/tags/user-following.tag b/src/web/app/mobile/tags/user-following.tag
index b214789aa..778eb08e1 100644
--- a/src/web/app/mobile/tags/user-following.tag
+++ b/src/web/app/mobile/tags/user-following.tag
@@ -8,18 +8,21 @@
 	<script>
 		this.mixin('api');
 
-		this.user = this.opts.user
+		this.user = this.opts.user;
 
 		this.fetch = (iknow, limit, cursor, cb) => {
 			this.api('users/following', {
-				user_id: this.user.id
-				iknow: iknow
-				limit: limit
-				cursor: if cursor? then cursor else undefined
-			.then cb
+				user_id: this.user.id,
+				iknow: iknow,
+				limit: limit,
+				cursor: cursor ? cursor : undefined
+			}).then(cb);
+		};
 
 		this.on('mount', () => {
 			this.refs.list.on('loaded', () => {
 				this.trigger('loaded');
+			});
+		});
 	</script>
 </mk-user-following>
diff --git a/src/web/app/mobile/tags/user-timeline.tag b/src/web/app/mobile/tags/user-timeline.tag
index 71fb1ac27..fb316dbdf 100644
--- a/src/web/app/mobile/tags/user-timeline.tag
+++ b/src/web/app/mobile/tags/user-timeline.tag
@@ -14,18 +14,22 @@
 		this.user = this.opts.user;
 		this.withMedia = this.opts.withMedia;
 
-		this.init = new Promise (res, rej) =>
+		this.init = new Promise((res, rej) => {
 			this.api('users/posts', {
-				user_id: this.user.id
-				with_media: @withMedia
+				user_id: this.user.id,
+				with_media: this.withMedia
 			}).then(posts => {
-				res posts
+				res(posts);
 				this.trigger('loaded');
+			});
+		});
 
 		this.more = () => {
 			this.api('users/posts', {
-				user_id: this.user.id
-				with_media: this.withMedia
-				max_id: this.refs.timeline.tail!.id
+				user_id: this.user.id,
+				with_media: this.withMedia,
+				max_id: this.refs.timeline.tail().id
+			});
+		};
 	</script>
 </mk-user-timeline>
diff --git a/src/web/app/mobile/tags/users-list.tag b/src/web/app/mobile/tags/users-list.tag
index ef225d5b5..82dfa3df4 100644
--- a/src/web/app/mobile/tags/users-list.tag
+++ b/src/web/app/mobile/tags/users-list.tag
@@ -72,45 +72,48 @@
 	<script>
 		this.mixin('i');
 
-		this.limit = 30users
-		this.mode = 'all' 
+		this.limit = 30;
+		this.mode = 'all';
 
-		this.fetching = true
-		this.more-fetching = false
+		this.fetching = true;
+		this.moreFetching = false;
 
 		this.on('mount', () => {
-			@fetch =>
-				this.trigger('loaded');
+			this.fetch(() => this.trigger('loaded'));
+		});
 
-		this.fetch = (cb) => {
-			this.fetching = true
-			this.update();
-			obj <~ this.opts.fetch do
-				this.mode == 'iknow' 
-				@limit
-				null
-			this.users = obj.users
-			this.next = obj.next
-			this.fetching = false
-			this.update();
-			if cb? then cb!
+		this.fetch = cb => {
+			this.update({
+				fetching: true
+			});
+			this.opts.fetch(this.mode == 'iknow', this.limit, null, obj => {
+				this.update({
+					fetching: false,
+					users: obj.users,
+					next: obj.next
+				});
+				if (cb) cb();
+			});
+		};
 
 		this.more = () => {
-			this.more-fetching = true
-			this.update();
-			obj <~ this.opts.fetch do
-				this.mode == 'iknow' 
-				@limit
-				@cursor
-			this.users = this.users.concat obj.users
-			this.next = obj.next
-			this.more-fetching = false
-			this.update();
+			this.update({
+				moreFetching: true
+			});
+			this.opts.fetch(this.mode == 'iknow', this.limit, this.cursor, obj => {
+				this.update({
+					moreFetching: false,
+					users: this.users.concat(obj.users),
+					next: obj.next
+				});
+			});
+		};
 
-		this.set-mode = (mode) => {
-			@update do
+		this.setMode = mode => {
+			this.update({
 				mode: mode
-
-			@fetch!
+			});
+			this.fetch();
+		};
 	</script>
 </mk-users-list>

From 1f3e128ed50ccb27096ab75f9e93cbcf8b5cef2e Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 22 Feb 2017 01:20:57 +0900
Subject: [PATCH 31/32] Fix

---
 src/web/app/common/tags/messaging/room.tag       |  4 ++--
 src/web/app/common/tags/number.tag               |  3 +--
 src/web/app/desktop/tags/analog-clock.tag        | 10 ++++------
 src/web/app/desktop/tags/drive/file.tag          |  4 ++--
 .../app/desktop/tags/home-widgets/calendar.tag   |  2 +-
 .../desktop/tags/home-widgets/notifications.tag  |  2 +-
 src/web/app/desktop/tags/repost-form.tag         |  1 +
 src/web/app/desktop/tags/timeline-post-sub.tag   | 16 +++++++---------
 src/web/app/desktop/tags/ui.tag                  |  2 +-
 src/web/app/desktop/tags/user-timeline.tag       |  1 +
 src/web/app/mobile/tags/drive/file.tag           |  2 +-
 src/web/app/mobile/tags/page/drive.tag           |  1 +
 src/web/app/mobile/tags/user-followers.tag       |  2 +-
 webpack.config.ts                                |  1 -
 14 files changed, 24 insertions(+), 27 deletions(-)

diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
index cb676badb..c7fed91db 100644
--- a/src/web/app/common/tags/messaging/room.tag
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -136,8 +136,8 @@
 		this.connection = new this.MessagingStreamConnection(this.I, this.user.id);
 
 		this.on('mount', () => {
-			this.connection.event.on('message' this.onMessage);
-			this.connection.event.on('read' this.onRead);
+			this.connection.event.on('message', this.onMessage);
+			this.connection.event.on('read', this.onRead);
 
 			document.addEventListener('visibilitychange', this.onVisibilitychange);
 
diff --git a/src/web/app/common/tags/number.tag b/src/web/app/common/tags/number.tag
index 212a80b73..7dcbceba6 100644
--- a/src/web/app/common/tags/number.tag
+++ b/src/web/app/common/tags/number.tag
@@ -2,13 +2,12 @@
 	<style>
 		:scope
 			display inline
-
 	</style>
 	<script>
 		this.on('mount', () => {
 			// https://github.com/riot/riot/issues/2103
 			//value = this.opts.value
-			const value = this.opts.riotValue;
+			let value = this.opts.riotValue;
 			const max = this.opts.max;
 
 			if (max != null && value > max) value = max;
diff --git a/src/web/app/desktop/tags/analog-clock.tag b/src/web/app/desktop/tags/analog-clock.tag
index 4ac6d2281..c7f200746 100644
--- a/src/web/app/desktop/tags/analog-clock.tag
+++ b/src/web/app/desktop/tags/analog-clock.tag
@@ -8,12 +8,10 @@
 				height 256px
 	</style>
 	<script>
-		class Vec2 {
-			constructor(x, y) {
-				this.x = x;
-				this.y = y;
-			}
-		}
+		const Vec2 = function(x, y) {
+			this.x = x;
+			this.y = y;
+		};
 
 		this.on('mount', () => {
 			this.draw()
diff --git a/src/web/app/desktop/tags/drive/file.tag b/src/web/app/desktop/tags/drive/file.tag
index 5d12f2419..d92d4bbaf 100644
--- a/src/web/app/desktop/tags/drive/file.tag
+++ b/src/web/app/desktop/tags/drive/file.tag
@@ -144,7 +144,7 @@
 
 	</style>
 	<script>
-		this.bytesToSize = require('../../../common/scripts/bytesToSize.js');
+		this.bytesToSize = require('../../../common/scripts/bytes-to-size');
 
 		this.mixin('i');
 
@@ -203,7 +203,7 @@
 				type: 'file',
 				id: this.file.id,
 				file: this.file
-			});
+			}));
 			this.isDragging = true;
 
 			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
diff --git a/src/web/app/desktop/tags/home-widgets/calendar.tag b/src/web/app/desktop/tags/home-widgets/calendar.tag
index 2a455edff..9aa4ac632 100644
--- a/src/web/app/desktop/tags/home-widgets/calendar.tag
+++ b/src/web/app/desktop/tags/home-widgets/calendar.tag
@@ -115,7 +115,7 @@
 			this.year = ny;
 			this.month = nm + 1;
 			this.day = nd;
-			this.weekDay = ['日', '月', '火', '水' '木', '金', '土'][now.getDay()];
+			this.weekDay = ['日', '月', '火', '水', '木', '金', '土'][now.getDay()];
 
 			this.dayNumer   = now - new Date(ny, nm, nd);
 			this.dayDenom   = 1000/*ms*/ * 60/*s*/ * 60/*m*/ * 24/*h*/;
diff --git a/src/web/app/desktop/tags/home-widgets/notifications.tag b/src/web/app/desktop/tags/home-widgets/notifications.tag
index 5ed26b5d7..5d71407b4 100644
--- a/src/web/app/desktop/tags/home-widgets/notifications.tag
+++ b/src/web/app/desktop/tags/home-widgets/notifications.tag
@@ -44,7 +44,7 @@
 	</style>
 	<script>
 		this.settings = () => {
-			const w = riot.mount(document.body.appendChild(document.createElement('mk-settings-window')[0];
+			const w = riot.mount(document.body.appendChild(document.createElement('mk-settings-window')))[0];
 			w.switch('notification');
 		};
 	</script>
diff --git a/src/web/app/desktop/tags/repost-form.tag b/src/web/app/desktop/tags/repost-form.tag
index de10a37f0..e5101d9f2 100644
--- a/src/web/app/desktop/tags/repost-form.tag
+++ b/src/web/app/desktop/tags/repost-form.tag
@@ -139,6 +139,7 @@
 					wait: false
 				});
 			});
+		};
 
 		this.onquote = () => {
 			this.quote = true;
diff --git a/src/web/app/desktop/tags/timeline-post-sub.tag b/src/web/app/desktop/tags/timeline-post-sub.tag
index 2c76527f1..905bc7aac 100644
--- a/src/web/app/desktop/tags/timeline-post-sub.tag
+++ b/src/web/app/desktop/tags/timeline-post-sub.tag
@@ -8,15 +8,6 @@
 			</div>
 		</div>
 	</article>
-	<script>
-		this.mixin('date-stringify');
-		this.mixin('user-preview');
-
-		this.post = this.opts.post
-
-		this.title = @date-stringify this.post.created_at
-
-	</script>
 	<style>
 		:scope
 			display block
@@ -97,4 +88,11 @@
 								font-size 80%
 
 	</style>
+	<script>
+		this.mixin('date-stringify');
+		this.mixin('user-preview');
+
+		this.post = this.opts.post;
+		this.title = this.dateStringify(this.post.created_at);
+	</script>
 </mk-timeline-post-sub>
diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag
index 832299e32..0669d252a 100644
--- a/src/web/app/desktop/tags/ui.tag
+++ b/src/web/app/desktop/tags/ui.tag
@@ -14,7 +14,7 @@
 		this.mixin('i');
 
 		this.openPostForm = () => {
-			riot.mount(document.body.appendChild(document.createElement('mk-post-form-window');
+			riot.mount(document.body.appendChild(document.createElement('mk-post-form-window')));
 		};
 
 		this.on('mount', () => {
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index e8ff3dc05..4851eb0a1 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -70,6 +70,7 @@
 				});
 
 				this.fetch(() => this.trigger('loaded'));
+			});
 		});
 
 		this.on('unmount', () => {
diff --git a/src/web/app/mobile/tags/drive/file.tag b/src/web/app/mobile/tags/drive/file.tag
index f800fd69e..4b8216219 100644
--- a/src/web/app/mobile/tags/drive/file.tag
+++ b/src/web/app/mobile/tags/drive/file.tag
@@ -122,7 +122,7 @@
 
 	</style>
 	<script>
-		this.bytesToSize = require('../../../common/scripts/bytesToSize.js');
+		this.bytesToSize = require('../../../common/scripts/bytes-to-size');
 
 		this.browser = this.parent;
 		this.file = this.opts.file;
diff --git a/src/web/app/mobile/tags/page/drive.tag b/src/web/app/mobile/tags/page/drive.tag
index c4cc64261..a064a0559 100644
--- a/src/web/app/mobile/tags/page/drive.tag
+++ b/src/web/app/mobile/tags/page/drive.tag
@@ -64,5 +64,6 @@
 					type: file.type
 				});
 			});
+		});
 	</script>
 </mk-drive-page>
diff --git a/src/web/app/mobile/tags/user-followers.tag b/src/web/app/mobile/tags/user-followers.tag
index 3a1fc1d4b..e939da6c6 100644
--- a/src/web/app/mobile/tags/user-followers.tag
+++ b/src/web/app/mobile/tags/user-followers.tag
@@ -23,6 +23,6 @@
 			this.refs.list.on('loaded', () => {
 				this.trigger('loaded');
 			});
-		};
+		});
 	</script>
 </mk-user-followers>
diff --git a/webpack.config.ts b/webpack.config.ts
index 6928536ff..66d4eb2e1 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -31,7 +31,6 @@ module.exports = (config, commit, env) => {
 					loader: 'riot-tag-loader',
 					query: {
 						hot: false,
-						type: 'es6',
 						style: 'stylus',
 						expr: false,
 						compact: true,

From f0b071893296e323df2ed2bdb06dbe794d72258d Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 22 Feb 2017 02:05:44 +0900
Subject: [PATCH 32/32] Fix bugs

---
 src/web/app/common/tags/signup.tag                  |  3 ++-
 src/web/app/desktop/tags/analog-clock.tag           | 12 ++++++------
 src/web/app/desktop/tags/crop-window.tag            |  2 +-
 src/web/app/desktop/tags/drive/browser.tag          |  6 +++---
 src/web/app/desktop/tags/drive/file-contextmenu.tag |  1 -
 src/web/app/desktop/tags/home-widgets/timeline.tag  |  2 +-
 src/web/app/desktop/tags/post-form.tag              |  4 ++--
 src/web/app/desktop/tags/ui-header-clock.tag        |  5 ++++-
 src/web/app/desktop/tags/user-photos.tag            |  2 +-
 src/web/app/mobile/tags/drive.tag                   |  8 ++++----
 src/web/app/mobile/tags/drive/folder.tag            |  2 +-
 src/web/app/mobile/tags/post-form.tag               |  4 ++--
 src/web/app/mobile/tags/timeline-post.tag           |  2 +-
 13 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag
index dafdf51e1..f0358e232 100644
--- a/src/web/app/common/tags/signup.tag
+++ b/src/web/app/common/tags/signup.tag
@@ -249,6 +249,7 @@
 
 			const strength = this.getPasswordStrength(password);
 			this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low';
+			this.update();
 			this.refs.passwordMetar.style.width = `${strength * 100}%`;
 		};
 
@@ -256,7 +257,7 @@
 			const password = this.refs.password.value;
 			const retypedPassword = this.refs.passwordRetype.value;
 
-			if (retyped-password == '') {
+			if (retypedPassword == '') {
 				this.passwordRetypeState = null;
 				return;
 			}
diff --git a/src/web/app/desktop/tags/analog-clock.tag b/src/web/app/desktop/tags/analog-clock.tag
index c7f200746..dcf4acaff 100644
--- a/src/web/app/desktop/tags/analog-clock.tag
+++ b/src/web/app/desktop/tags/analog-clock.tag
@@ -43,13 +43,13 @@
 					const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
 					ctx.beginPath();
 					ctx.lineWidth = 1;
-					ctx.moveTo((canv-w / 2) + uv.x * lineStart, (canv-h / 2) + uv.y * lineStart);
+					ctx.moveTo((canvW / 2) + uv.x * lineStart, (canvH / 2) + uv.y * lineStart);
 					if (i % 5 == 0) {
 						ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)';
-						ctx.lineTo((canv-w / 2) + uv.x * longLineEnd, (canv-h / 2) + uv.y * longLineEnd);
+						ctx.lineTo((canvW / 2) + uv.x * longLineEnd, (canvH / 2) + uv.y * longLineEnd);
 					} else {
 						ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
-						ctx.lineTo((canv-w / 2) + uv.x * shortLineEnd, (canv-h / 2) + uv.y * shortLineEnd);
+						ctx.lineTo((canvW / 2) + uv.x * shortLineEnd, (canvH / 2) + uv.y * shortLineEnd);
 					}
 					ctx.stroke();
 				}
@@ -58,7 +58,7 @@
 			{ // 分
 				const angle = Math.PI * (m + s / 60) / 30;
 				const length = Math.min(canvW, canvH) / 2.6;
-				const uv = new vec2(Math.sin(angle), -Math.cos(angle));
+				const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
 				ctx.beginPath();
 				ctx.strokeStyle = '#ffffff';
 				ctx.lineWidth = 2;
@@ -70,7 +70,7 @@
 			{ // 時
 				const angle = Math.PI * (h % 12 + m / 60) / 6;
 				const length = Math.min(canvW, canvH) / 4;
-				const uv = new vec2(Math.sin(angle), -Math.cos(angle));
+				const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
 				ctx.beginPath();
 				ctx.strokeStyle = CONFIG.themeColor;
 				ctx.lineWidth = 2;
@@ -82,7 +82,7 @@
 			{ // 秒
 				const angle = Math.PI * s / 30;
 				const length = Math.min(canvW, canvH) / 2.6;
-				const uv = new vec2(Math.sin(angle), -Math.cos(angle));
+				const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
 				ctx.beginPath();
 				ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
 				ctx.lineWidth = 1;
diff --git a/src/web/app/desktop/tags/crop-window.tag b/src/web/app/desktop/tags/crop-window.tag
index c5c186555..2cadc2994 100644
--- a/src/web/app/desktop/tags/crop-window.tag
+++ b/src/web/app/desktop/tags/crop-window.tag
@@ -169,7 +169,7 @@
 			this.img = this.refs.window.refs.img;
 			this.cropper = new this.Cropper(this.img, {
 				aspectRatio: this.aspectRatio,
-				highlight: no,
+				highlight: false,
 				viewMode: 1
 			});
 		});
diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag
index 989ec48ae..1e8b17cfc 100644
--- a/src/web/app/desktop/tags/drive/browser.tag
+++ b/src/web/app/desktop/tags/drive/browser.tag
@@ -659,10 +659,10 @@
 			});
 
 			let flag = false;
-			complete = () => {
+			const complete = () => {
 				if (flag) {
-					fetchedFolders.forEach(folder => this.addFolder);
-					fetchedFiles.forEach(file => this.addFile);
+					fetchedFolders.forEach(this.addFolder);
+					fetchedFiles.forEach(this.addFile);
 					this.update({
 						fetching: false
 					});
diff --git a/src/web/app/desktop/tags/drive/file-contextmenu.tag b/src/web/app/desktop/tags/drive/file-contextmenu.tag
index 733ee853f..29f1befc4 100644
--- a/src/web/app/desktop/tags/drive/file-contextmenu.tag
+++ b/src/web/app/desktop/tags/drive/file-contextmenu.tag
@@ -39,7 +39,6 @@
 		this.mixin('i');
 		this.mixin('update-avatar');
 		this.mixin('update-banner');
-		this.mixin('update-wallpaper');
 		this.mixin('input-dialog');
 		this.mixin('NotImplementedException');
 
diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag
index 138ff5ed1..a0a8790ea 100644
--- a/src/web/app/desktop/tags/home-widgets/timeline.tag
+++ b/src/web/app/desktop/tags/home-widgets/timeline.tag
@@ -62,7 +62,7 @@
 		});
 
 		this.onDocumentKeydown = e => {
-			if (e.target.tagName != 'INPUT' && tag != 'TEXTAREA') {
+			if (e.target.tagName != 'INPUT' && e.target.tagName != 'TEXTAREA') {
 				if (e.which == 84) { // t
 					this.refs.timeline.focus();
 				}
diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag
index 2e3262fed..3b80eee5d 100644
--- a/src/web/app/desktop/tags/post-form.tag
+++ b/src/web/app/desktop/tags/post-form.tag
@@ -305,7 +305,7 @@
 
 	</style>
 	<script>
-		getCat = require('../../common/scripts/get-cat');
+		const getCat = require('../../common/scripts/get-cat');
 
 		this.mixin('api');
 		this.mixin('notify');
@@ -379,7 +379,7 @@
 		};
 
 		this.onkeydown = e => {
-			if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.meta-key)) this.post();
+			if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey)) this.post();
 		};
 
 		this.onpaste = e => {
diff --git a/src/web/app/desktop/tags/ui-header-clock.tag b/src/web/app/desktop/tags/ui-header-clock.tag
index ce41083fc..48b142509 100644
--- a/src/web/app/desktop/tags/ui-header-clock.tag
+++ b/src/web/app/desktop/tags/ui-header-clock.tag
@@ -2,6 +2,7 @@
 	<div class="header">
 		<time ref="time">
 			<span class="yyyymmdd">{ yyyy }/{ mm }/{ dd }</span>
+			<br>
 			<span class="hhnn">{ hh }<span style="visibility:{ now.getSeconds() % 2 == 0 ? 'visible' : 'hidden' }">:</span>{ nn }</span>
 		</time>
 	</div>
@@ -61,8 +62,10 @@
 
 	</style>
 	<script>
+		this.now = new Date();
+
 		this.draw = () => {
-			this.now = new Date();
+			const now = this.now = new Date();
 			this.yyyy = now.getFullYear();
 			this.mm = ('0' + (now.getMonth() + 1)).slice(-2);
 			this.dd = ('0' + now.getDate()).slice(-2);
diff --git a/src/web/app/desktop/tags/user-photos.tag b/src/web/app/desktop/tags/user-photos.tag
index a72b1f302..86f12aceb 100644
--- a/src/web/app/desktop/tags/user-photos.tag
+++ b/src/web/app/desktop/tags/user-photos.tag
@@ -81,7 +81,7 @@
 					this.initializing = false;
 					posts.forEach(post => {
 						post.media.forEach(media => {
-							if (this.images.length < 9) this.images.push(image);
+							if (this.images.length < 9) this.images.push(media);
 						});
 					});
 					this.update();
diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag
index 707ec9478..35b9b6541 100644
--- a/src/web/app/mobile/tags/drive.tag
+++ b/src/web/app/mobile/tags/drive.tag
@@ -198,7 +198,7 @@
 		};
 
 		this.move = ev => {
-			this.move(ev.item.folder);
+			this.cd(ev.item.folder);
 		};
 
 		this.cd = (target, silent = false) => {
@@ -333,10 +333,10 @@
 			});
 
 			let flag = false;
-			complete = () => {
+			const complete = () => {
 				if (flag) {
-					fetchedFolders.forEach(folder => this.addFolder);
-					fetchedFiles.forEach(file => this.addFile);
+					fetchedFolders.forEach(this.addFolder);
+					fetchedFiles.forEach(this.addFile);
 					this.update({
 						fetching: false
 					});
diff --git a/src/web/app/mobile/tags/drive/folder.tag b/src/web/app/mobile/tags/drive/folder.tag
index 093e74292..27e86662c 100644
--- a/src/web/app/mobile/tags/drive/folder.tag
+++ b/src/web/app/mobile/tags/drive/folder.tag
@@ -41,7 +41,7 @@
 		this.folder = this.opts.folder;
 
 		this.onclick = () => {
-			this.browser.move(this.folder);
+			this.browser.cd(this.folder);
 		};
 	</script>
 </mk-drive-folder>
diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag
index 397475e3f..353db0154 100644
--- a/src/web/app/mobile/tags/post-form.tag
+++ b/src/web/app/mobile/tags/post-form.tag
@@ -182,7 +182,7 @@
 
 	</style>
 	<script>
-		getCat = require('../../common/scripts/get-cat');
+		const getCat = require('../../common/scripts/get-cat');
 
 		this.mixin('api');
 
@@ -204,7 +204,7 @@
 		});
 
 		this.onkeydown = e => {
-			if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.meta-key)) this.post();
+			if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey)) this.post();
 		};
 
 		this.onpaste = e => {
diff --git a/src/web/app/mobile/tags/timeline-post.tag b/src/web/app/mobile/tags/timeline-post.tag
index 0a6db9a92..8662eadb8 100644
--- a/src/web/app/mobile/tags/timeline-post.tag
+++ b/src/web/app/mobile/tags/timeline-post.tag
@@ -298,7 +298,7 @@
 		this.mixin('api');
 		this.mixin('text');
 		this.mixin('get-post-summary');
-		this.mixin('openPostForm');
+		this.mixin('open-post-form');
 
 		this.post = this.opts.post;
 		this.isRepost = this.post.repost != null && this.post.text == null;