From 441796f845dc60f9f499b9f7f4889081a7be6bbe Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sat, 21 Apr 2018 18:59:16 +0900
Subject: [PATCH] Add search syntax

---
 .../app/common/views/components/google.vue    | 67 +++++++++++++++++++
 .../app/common/views/components/note-html.ts  |  8 +++
 src/text/html.ts                              |  7 ++
 src/text/parse/elements/search.ts             | 13 ++++
 4 files changed, 95 insertions(+)
 create mode 100644 src/client/app/common/views/components/google.vue
 create mode 100644 src/text/parse/elements/search.ts

diff --git a/src/client/app/common/views/components/google.vue b/src/client/app/common/views/components/google.vue
new file mode 100644
index 0000000000..92817d3c1f
--- /dev/null
+++ b/src/client/app/common/views/components/google.vue
@@ -0,0 +1,67 @@
+<template>
+<div class="mk-google">
+	<input type="search" v-model="query" :placeholder="q">
+	<button @click="search">検索</button>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+	props: ['q'],
+	data() {
+		return {
+			query: null
+		};
+	},
+	mounted() {
+		this.query = this.q;
+	},
+	methods: {
+		search() {
+			window.open(`https://www.google.com/?#q=${this.query}`, '_blank');
+		}
+	}
+});
+</script>
+
+<style lang="stylus" scoped>
+root(isDark)
+	display flex
+	margin 8px 0
+
+	> input
+		flex-shrink 1
+		padding 10px
+		width 100%
+		height 40px
+		font-family sans-serif
+		font-size 16px
+		color isDark ? #dee4e8 : #55595c
+		background isDark ? #191b22 : #fff
+		border solid 1px isDark ? #495156 : #dadada
+		border-radius 4px 0 0 4px
+
+		&:hover
+			border-color isDark ? #777c86 : #b0b0b0
+
+	> button
+		flex-shrink 0
+		padding 0 16px
+		border solid 1px isDark ? #495156 : #dadada
+		border-left none
+		border-radius 0 4px 4px 0
+
+		&:hover
+			background-color isDark ? #2e3440 : #eee
+
+		&:active
+			box-shadow 0 2px 4px rgba(#000, 0.15) inset
+
+.mk-google[data-darkmode]
+	root(true)
+
+.mk-google:not([data-darkmode])
+	root(false)
+
+</style>
diff --git a/src/client/app/common/views/components/note-html.ts b/src/client/app/common/views/components/note-html.ts
index 38f6251cf7..f86b50659e 100644
--- a/src/client/app/common/views/components/note-html.ts
+++ b/src/client/app/common/views/components/note-html.ts
@@ -4,6 +4,7 @@ import parse from '../../../../../text/parse';
 import getAcct from '../../../../../acct/render';
 import { url } from '../../../config';
 import MkUrl from './url.vue';
+import MkGoogle from './google.vue';
 
 const flatten = list => list.reduce(
 	(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
@@ -145,6 +146,13 @@ export default Vue.component('mk-note-html', {
 					const emoji = emojilib.lib[token.emoji];
 					return createElement('span', emoji ? emoji.char : token.content);
 
+				case 'search':
+					return createElement(MkGoogle, {
+						props: {
+							q: token.query
+						}
+					});
+
 				default:
 					console.log('unknown ast type:', token.type);
 			}
diff --git a/src/text/html.ts b/src/text/html.ts
index 55265c206a..f33ef4997b 100644
--- a/src/text/html.ts
+++ b/src/text/html.ts
@@ -75,6 +75,13 @@ const handlers = {
 		a.href = url;
 		a.textContent = url;
 		document.body.appendChild(a);
+	},
+
+	search({ document }, { content, query }) {
+		const a = document.createElement('a');
+		a.href = `https://www.google.com/?#q=${query}`;
+		a.textContent = content;
+		document.body.appendChild(a);
 	}
 };
 
diff --git a/src/text/parse/elements/search.ts b/src/text/parse/elements/search.ts
new file mode 100644
index 0000000000..12ee8ecbb8
--- /dev/null
+++ b/src/text/parse/elements/search.ts
@@ -0,0 +1,13 @@
+/**
+ * Search
+ */
+
+module.exports = text => {
+	const match = text.match(/^(.+?) 検索(\n|$)/);
+	if (!match) return null;
+	return {
+		type: 'search',
+		content: match[0],
+		query: match[1]
+	};
+};