diff --git a/src/common/text/elements/code.js b/src/common/text/elements/code.js
index d046716ed..190a090d9 100644
--- a/src/common/text/elements/code.js
+++ b/src/common/text/elements/code.js
@@ -11,7 +11,191 @@ module.exports = {
 		return {
 			type: 'code',
 			content: code,
-			code: code.substr(3, code.length - 6).trim()
+			code: code.substr(3, code.length - 6).trim(),
+			codeHtml: genHtml(code.substr(3, code.length - 6).trim())
 		};
 	}
 };
+
+function escape(text) {
+	return text
+		.replace(/>/g, '>')
+		.replace(/</g, '&lt;');
+}
+
+// 文字数が多い順にソートします
+// そうしないと、「function」という文字列が与えられたときに「func」が先にマッチしてしまう可能性があるためです
+const keywords = [
+	'true',
+	'false',
+	'null',
+	'nil',
+	'undefined',
+	'var',
+	'const',
+	'let',
+	'mut',
+	'if',
+	'then',
+	'else',
+	'switch',
+	'case',
+	'for',
+	'each',
+	'in',
+	'while',
+	'loop',
+	'continue',
+	'break',
+	'do',
+	'goto',
+	'end',
+	'function',
+	'func',
+	'fn',
+	'return',
+	'async',
+	'await',
+	'require',
+	'import',
+	'export',
+	'new',
+	'this',
+	'class',
+	'constructor'
+].sort((a, b) => b.length - a.length);
+
+const symbols = [
+	'=',
+	'+',
+	'-',
+	'*',
+	'/',
+	'%',
+	'^',
+	'&',
+	'|',
+	'>',
+	'<',
+	'~'
+];
+
+const elements = [
+	// comment
+	code => {
+		if (code.substr(0, 2) != '//') return null;
+		const comment = code.match(/^\/\/(.+?)\n/)[0];
+		return {
+			html: `<span class="comment">${escape(comment)}</span>`,
+			next: comment.length
+		};
+	},
+
+	// string
+	code => {
+		if (!/^['"`]/.test(code)) return null;
+		const begin = code[0];
+		let str = begin;
+		let thisIsNotAString = false;
+		for (i = 1; i < code.length; i++) {
+			const char = code[i];
+			if (char == '\\') {
+				i++;
+				continue;
+			} else if (char == begin) {
+				str += char;
+				break;
+			} else if (char == '\n' || i == (code.length - 1)) {
+				thisIsNotAString = true;
+				break;
+			} else {
+				str += char;
+			}
+		}
+		if (thisIsNotAString) {
+			return null;
+		} else {
+			return {
+				html: `<span class="string">${escape(str)}</span>`,
+				next: str.length
+			};
+		}
+	},
+
+	// number
+	(code, i, source) => {
+		const prev = source[i - 1];
+		if (prev && /[a-zA-Z]/.test(prev)) return null;
+		if (!/^[0-9]+/.test(code)) return null;
+		const match = code.match(/^[0-9]+/)[0];
+		if (match) {
+			return {
+				html: `<span class="number">${match}</span>`,
+				next: match.length
+			};
+		} else {
+			return null;
+		}
+	},
+
+	// keyword
+	code => {
+		const match = keywords.filter(k => code.substr(0, k.length) == k)[0];
+		if (match) {
+			if (/^[a-zA-Z]/.test(code.substr(match.length))) return null;
+			return {
+				html: `<span class="keyword ${match}">${match}</span>`,
+				next: match.length
+			};
+		} else {
+			return null;
+		}
+	},
+
+	// symbol
+	code => {
+		const match = symbols.filter(s => code[0] == s)[0];
+		if (match) {
+			return {
+				html: `<span class="symbol">${match}</span>`,
+				next: 1
+			};
+		} else {
+			return null;
+		}
+	}
+];
+
+// specify lang is todo
+function genHtml(source, lang) {
+	let code = source;
+	let html = '';
+
+	function push(token) {
+		html += token.html;
+		code = code.substr(token.next);
+	}
+
+	let i = 0;
+
+	while (code != '') {
+		const parsed = elements.some(el => {
+			const e = el(code, i, source);
+			if (e) {
+				push(e);
+				return true;
+			}
+		});
+
+		if (!parsed) {
+			push({
+				html: escape(code[0]),
+				next: 1
+			});
+		}
+
+		i++;
+	}
+
+	return html;
+}
diff --git a/src/web/app/base.styl b/src/web/app/base.styl
index 5eab20548..4082fa24c 100644
--- a/src/web/app/base.styl
+++ b/src/web/app/base.styl
@@ -107,6 +107,29 @@ a
 	*
 		cursor pointer
 
+pre > code
+	.comment
+		opacity 0.5
+
+	.string
+		color #e96900
+
+	.keyword
+		color #2973b7
+
+		&.true
+		&.false
+		&.null
+		&.nil
+		&.undefined
+			color #ae81ff
+
+	.symbol
+		color #42b983
+
+	.number
+		color #ae81ff
+
 mk-locker
 	display block
 	position fixed
diff --git a/src/web/app/common/scripts/text-compiler.js b/src/web/app/common/scripts/text-compiler.js
index ab322764f..29b700e62 100644
--- a/src/web/app/common/scripts/text-compiler.js
+++ b/src/web/app/common/scripts/text-compiler.js
@@ -31,7 +31,7 @@ module.exports = function(tokens, shouldBreak, shouldEscape) {
 			case 'hashtag': // TODO
 				return '<a>' + escape(token.content) + '</a>';
 			case 'code':
-				return '<pre><code>' + escape(token.code) + '</code></pre>';
+				return '<pre><code>' + token.codeHtml + '</code></pre>';
 		}
 	}).join('');