Skip to content
This repository was archived by the owner on Dec 13, 2019. It is now read-only.

Commit b824043

Browse files
committed
feat: Add Search page
1 parent ed242a9 commit b824043

File tree

12 files changed

+193
-2
lines changed

12 files changed

+193
-2
lines changed

_config.yml

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ render_drafts: false
3232
relative_link: false
3333
future: true
3434

35+
search:
36+
path: search.xml
37+
field: all
38+
3539
markdown:
3640
gfm: true
3741
pedantic: false

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"hexo-generator-archive": "^0.1.2",
1616
"hexo-generator-category": "^0.1.2",
1717
"hexo-generator-index": "^0.2.0",
18+
"hexo-generator-search": "^1.0.2",
1819
"hexo-generator-sitemap": "^1.0.1",
1920
"hexo-generator-tag": "^0.1.1",
2021
"hexo-renderer-ejs": "^0.1.0",

source/guide/quasar-build-process.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Following lines will describe how everything is glued together.
77
## Source Files
88

99
### Javascript Files
10-
Javascript files are glued together using <a href="http://webpack.github.io/docs/" target="_blank">Webpack</a>. So you can use *require()* -- and *require.resolve()* -- for modularity. You must adhere to the <a href="https://webpack.github.io/docs/commonjs.html" target="_blank">CommonJS</a> format when writing *.js* files.
10+
Javascript files are glued together using <a href="http://webpack.github.io/docs/" target="_blank">Webpack</a>. So you can use *require()* -- and *require.resolve()* -- for modularity. You must adhere to the <a href="https://webpack.github.io/docs/commonjs.html" target="_blank">CommonJS2</a> format when writing *.js* files.
1111

1212
Take into consideration that the following files are taken as Webpack entry-points (take a good look at folders):
1313
* /js/*file-name*.js

source/search/index.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
search_index: true
3+
---

themes/quasar/layout/layout.ejs

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
<div id="main">
2929
<% if (page.blog_index) { %>
3030
<%- partial('partials/blog') %>
31+
<% } else if (page.search_index) { %>
32+
<%- partial('partials/search') %>
3133
<% } else { %>
3234
<%- body %>
3335
<% } %>
@@ -44,9 +46,13 @@
4446
</script>
4547
<%- partial('partials/ga') %>
4648
<% if (!isIndex) { %>
49+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
4750
<script src="https://cdnjs.cloudflare.com/ajax/libs/smooth-scroll/7.1.1/js/smooth-scroll.min.js"></script>
4851
<!-- build:js js/page-combined.js -->
4952
<script src="<%- config.root %>js/page.js"></script>
53+
<% if (page.search_index) { %>
54+
<script src="<%- config.root %>js/search.js"></script>
55+
<% } %>
5056
<!-- endbuild -->
5157
<% } %>
5258
</body>

themes/quasar/layout/partials/blog.ejs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
</ul>
55
</div>
66
<div class="content blog">
7-
<h1 style="margin-bottom:.5em">The Quasar Framework Blog</h1>
7+
<h1>The Quasar Framework Blog</h1>
88
<% site.posts.sort('date', -1).each(function (post) { %>
99
<div class="post">
1010
<h2><a href="<%- config.root + post.path %>"><%- post.title %></a></h2>

themes/quasar/layout/partials/main_menu.ejs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<li><a href="<%- config.root %>search/" class="nav-link<%- page.path.match(/search/) ? ' current' : '' %>"><i class="fa fa-search" style="vertical-align: middle"></i> Search</a></li>
12
<li><a href="<%- config.root %>guide/" class="nav-link<%- page.path.match(/guide/) ? ' current' : '' %>">Guide</a></li>
23
<li><a href="<%- config.root %>api/" class="nav-link<%- page.path.match(/api/) ? ' current' : '' %>">API</a></li>
34
<li><a href="<%- config.root %>blog/" class="nav-link<%- page.path.match(/blog/) ? ' current' : '' %>">Blog</a></li>
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<div class="sidebar sidebar-search-index">
2+
<ul class="main-menu">
3+
<%- partial('partials/main_menu') %>
4+
</ul>
5+
</div>
6+
<div class="content search">
7+
<h1 style="margin-bottom:.5em">Search Quasar Website</h1>
8+
<input autofocus type="text" id="local-search-input" placeholder="Type here">
9+
<div id="local-search-result"></div>
10+
</div>

themes/quasar/source/css/_common.styl

+13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ h1, h2, h3, h4, strong
2020
font-weight 600
2121
color $dark
2222

23+
input
24+
vertical-align middle
25+
border 1px solid $border
26+
border-radius 3px
27+
box-shadow $shadow
28+
line-height 20px
29+
font-size 16px
30+
padding 12px 10px
31+
width 100%
32+
cursor pointer
33+
outline 0
34+
box-sizing border-box
35+
2336
code, pre
2437
font-family $code-font
2538
font-size $code-font-size

themes/quasar/source/css/_search.styl

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.content.search
2+
margin-left 50px
3+
h1
4+
margin 0 0 .5em
5+
ul
6+
list-style-type none
7+
padding-left 0
8+
p.search-result
9+
margin-top 0
10+
li
11+
margin .5em 0 .5em
12+
border-bottom 1px solid $border
13+
border-radius $radius
14+
padding 10px
15+
&:hover
16+
background-color #EEE
17+
a.search-result-title
18+
font-weight bold
19+
color $main
20+
font-size 16px
21+
a.search-result
22+
color $medium
23+
font-weight 400
24+
25+
@media screen and (max-width: 720px)
26+
.content.search
27+
margin-left 0
28+
29+
@media screen and (min-width: 720px)
30+
.sidebar.sidebar-search-index
31+
display none

themes/quasar/source/css/page.styl

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@import "_common"
22
@import "_blog"
3+
@import "_search"
34

45
$header-height = 40px
56

themes/quasar/source/js/search.js

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
$(function() {
2+
'use strict';
3+
4+
function titleCase(string) {
5+
return string.replace(/\w\S*/g, function(txt) {return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
6+
}
7+
8+
function parseResponse(xmlResponse) {
9+
// get the contents from search data
10+
var datas = $('entry', xmlResponse).map(function() {
11+
return {
12+
title: $('title', this).text(),
13+
content: $('content', this).text(),
14+
url: $('url', this).text()
15+
};
16+
}).get();
17+
18+
var $input = document.getElementById('local-search-input');
19+
var $resultContent = document.getElementById('local-search-result');
20+
21+
$('input#local-search-input').keyup(function(e) {
22+
if (e.keyCode == 27) {
23+
$(this).val('');
24+
$resultContent.innerHTML = '';
25+
}
26+
});
27+
28+
$input.addEventListener('input', function() {
29+
var str = '<ul>';
30+
var keywords = this.value.trim();
31+
32+
$resultContent.innerHTML = '';
33+
if (keywords.length <= 0) {
34+
return;
35+
}
36+
keywords = keywords.toLowerCase().split(/[\s\-]+/);
37+
38+
// perform local searching
39+
datas.forEach(function(data) {
40+
var isMatch = true;
41+
var contentIndex = [];
42+
var dataTitle = data.title.trim().toLowerCase();
43+
var dataContent = data.content.trim().replace(/<[^>]+>/g,'').toLowerCase();
44+
var dataUrl = data.url;
45+
var indexTitle = -1;
46+
var indexContent = -1;
47+
var firstOccur = -1;
48+
49+
// only match artiles with not empty titles and contents
50+
if(dataTitle != '' && dataContent != '') {
51+
keywords.forEach(function(keyword, i) {
52+
indexTitle = dataTitle.indexOf(keyword);
53+
indexContent = dataContent.indexOf(keyword);
54+
55+
if (indexTitle < 0 && indexContent < 0) {
56+
isMatch = false;
57+
}
58+
else {
59+
if (indexContent < 0) {
60+
indexContent = 0;
61+
}
62+
if (i == 0) {
63+
firstOccur = indexContent;
64+
}
65+
// contentIndex.push({indexContent:indexContent, keyword_len:keyword_len});
66+
}
67+
});
68+
}
69+
70+
// show search results
71+
if (isMatch) {
72+
var content = data.content.trim().replace(/<[^>]+>/g,'');
73+
74+
if (!content.length) {
75+
return;
76+
}
77+
78+
str += '<li><a href="' + dataUrl + '" class="search-result-title">' + titleCase(dataTitle) + '</a>';
79+
80+
if (firstOccur >= 0) {
81+
// cut out 100 characters
82+
var start = firstOccur - 100;
83+
var end = firstOccur + 100;
84+
85+
if (start < 0) {
86+
start = 0;
87+
}
88+
89+
if (start == 0) {
90+
end = 200;
91+
}
92+
93+
if (end > content.length) {
94+
end = content.length;
95+
}
96+
97+
var matchContent = content.substring(start, end);
98+
99+
// highlight all keywords
100+
keywords.forEach(function(keyword) {
101+
var regS = new RegExp(keyword, 'gi');
102+
103+
matchContent = matchContent.replace(regS, '<code>' + keyword + '</code>');
104+
});
105+
106+
str += '<a class="search-result" href="' + dataUrl + '"><p>' + matchContent + '...</p></a>';
107+
}
108+
str += '</li>';
109+
}
110+
});
111+
str += '</ul>';
112+
$resultContent.innerHTML = str;
113+
});
114+
}
115+
116+
$.ajax({
117+
url: '/search.xml',
118+
dataType: 'xml',
119+
success: parseResponse
120+
});
121+
});

0 commit comments

Comments
 (0)