diff options
Diffstat (limited to 'plugins')
17 files changed, 1424 insertions, 0 deletions
diff --git a/plugins/__init__.py b/plugins/__init__.py new file mode 100644 index 00000000..fd7e25d7 --- /dev/null +++ b/plugins/__init__.py | |||
@@ -0,0 +1 @@ | |||
# Plugin modules go here. \ No newline at end of file | |||
diff --git a/plugins/localsearch/MIT-LICENSE.txt b/plugins/localsearch/MIT-LICENSE.txt new file mode 100644 index 00000000..f1310681 --- /dev/null +++ b/plugins/localsearch/MIT-LICENSE.txt | |||
@@ -0,0 +1,20 @@ | |||
1 | Tipue Search Copyright (c) 2012 Tipue | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining | ||
4 | a copy of this software and associated documentation files (the | ||
5 | "Software"), to deal in the Software without restriction, including | ||
6 | without limitation the rights to use, copy, modify, merge, publish, | ||
7 | distribute, sublicense, and/or sell copies of the Software, and to | ||
8 | permit persons to whom the Software is furnished to do so, subject to | ||
9 | the following conditions: | ||
10 | |||
11 | The above copyright notice and this permission notice shall be | ||
12 | included in all copies or substantial portions of the Software. | ||
13 | |||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
diff --git a/plugins/localsearch/README.md b/plugins/localsearch/README.md new file mode 100644 index 00000000..f7321da6 --- /dev/null +++ b/plugins/localsearch/README.md | |||
@@ -0,0 +1,15 @@ | |||
1 | If you don't want to depend on Google or DuckDuckGo to implement search for you, | ||
2 | or just want it to work even if you are offline, enable this plugin and the | ||
3 | search will be performed client side. It uses [Tipue Search](http://www.tipue.com/search/) as its engine. | ||
4 | |||
5 | In ordrer to set up Tipue, you will need: | ||
6 | |||
7 | * the sample config from `conf.py.sample` and a page set up to render `localsearch.tmpl` (which you may customize) — | ||
8 | an example is in `search-EXAMPLE.html` | ||
9 | * or the alternate sample config from `conf.py.sample.alt`, which uses a modal | ||
10 | and does not need another page | ||
11 | |||
12 | For more information about how to customize it and use it, please refer to the Tipue | ||
13 | docs at http://www.tipue.com/search/ | ||
14 | |||
15 | Tipue is under an MIT license (see MIT-LICENSE.txt) | ||
diff --git a/plugins/localsearch/conf.py.sample b/plugins/localsearch/conf.py.sample new file mode 100644 index 00000000..553abe65 --- /dev/null +++ b/plugins/localsearch/conf.py.sample | |||
@@ -0,0 +1,17 @@ | |||
1 | # This is an example that works well with Nikola's default Bootstrap3 theme. | ||
2 | # It displays the search field in the navigation bar, and the results | ||
3 | # on a separate page (which needs to be configured, see README.md). | ||
4 | # This snippet assumes the page ends up at /search/. | ||
5 | |||
6 | SEARCH_FORM = """ | ||
7 | <form class="navbar-form navbar-left" action="/search/" role="search"> | ||
8 | <div class="form-group"> | ||
9 | <input type="text" class="form-control" id="tipue_search_input" name="q" placeholder="Search" autocomplete="off"> | ||
10 | </div> | ||
11 | <button type="submit" class="btn btn-default">Submit</button> | ||
12 | </form> | ||
13 | """ | ||
14 | |||
15 | EXTRA_HEAD_DATA = """ | ||
16 | <link rel="stylesheet" type="text/css" href="/assets/css/tipuesearch.css"> | ||
17 | """ | ||
diff --git a/plugins/localsearch/conf.py.sample.alt b/plugins/localsearch/conf.py.sample.alt new file mode 100644 index 00000000..8c5c0285 --- /dev/null +++ b/plugins/localsearch/conf.py.sample.alt | |||
@@ -0,0 +1,53 @@ | |||
1 | # Alternate conf.py.sample -- for displaying in a modal dialog. | ||
2 | SEARCH_FORM = """ | ||
3 | <span class="navbar-form navbar-left"> | ||
4 | <input type="text" id="tipue_search_input" class="form-control" placeholder="Search"> | ||
5 | </span>""" | ||
6 | |||
7 | EXTRA_HEAD_DATA = """ | ||
8 | <link rel="stylesheet" type="text/css" href="/assets/css/tipuesearch.css"> | ||
9 | """ | ||
10 | |||
11 | BODY_END = """ | ||
12 | <!-- Modal --> | ||
13 | <div id="search-results" class="modal fade" role="dialog" style="height: 80%;"> | ||
14 | <div class="modal-dialog"> | ||
15 | |||
16 | <!-- Modal content--> | ||
17 | <div class="modal-content"> | ||
18 | <div class="modal-header"> | ||
19 | <button type="button" class="close" data-dismiss="modal">×</button> | ||
20 | <h4 class="modal-title">Search Results:</h4> | ||
21 | </div> | ||
22 | <div class="modal-body" id="tipue_search_content" style="max-height: 600px; overflow-y: auto;"> | ||
23 | </div> | ||
24 | <div class="modal-footer"> | ||
25 | <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> | ||
26 | </div> | ||
27 | </div> | ||
28 | |||
29 | </div> | ||
30 | </div> | ||
31 | <script> | ||
32 | var siteUrl = """ + json.dumps(SITE_URL) + """ | ||
33 | $(document).ready(function() { | ||
34 | $.when( | ||
35 | $.getScript( siteUrl + "/assets/js/tipuesearch_set.js" ), | ||
36 | $.getScript( siteUrl + "/assets/js/tipuesearch.js" ), | ||
37 | $.getScript( siteUrl + "/assets/js/tipuesearch_content.js" ), | ||
38 | $.Deferred(function( deferred ){ | ||
39 | $( deferred.resolve ); | ||
40 | }) | ||
41 | ).done(function() { | ||
42 | $('#tipue_search_input').tipuesearch({ | ||
43 | 'showUrl': false | ||
44 | }); | ||
45 | $('#tipue_search_input').keyup(function (e) { | ||
46 | if (e.keyCode == 13) { | ||
47 | $('#search-results').modal() | ||
48 | } | ||
49 | }); | ||
50 | }); | ||
51 | }); | ||
52 | </script> | ||
53 | """ | ||
diff --git a/plugins/localsearch/localsearch.plugin b/plugins/localsearch/localsearch.plugin new file mode 100644 index 00000000..c7b91f6d --- /dev/null +++ b/plugins/localsearch/localsearch.plugin | |||
@@ -0,0 +1,12 @@ | |||
1 | [Core] | ||
2 | Name = localsearch | ||
3 | Module = localsearch | ||
4 | |||
5 | [Nikola] | ||
6 | PluginCategory = LateTask | ||
7 | |||
8 | [Documentation] | ||
9 | Author = Roberto Alsina, Chris Warrick, Kevin Sheppard | ||
10 | Version = 0.3.0 | ||
11 | Website = http://plugins.getnikola.com/#localsearch | ||
12 | Description = Create data files for local search via Tipue | ||
diff --git a/plugins/localsearch/localsearch/__init__.py b/plugins/localsearch/localsearch/__init__.py new file mode 100644 index 00000000..fdc8874d --- /dev/null +++ b/plugins/localsearch/localsearch/__init__.py | |||
@@ -0,0 +1,106 @@ | |||
1 | # -*- coding: utf-8 -*- | ||
2 | |||
3 | # Copyright © 2012-2014 Roberto Alsina and others. | ||
4 | |||
5 | # Permission is hereby granted, free of charge, to any | ||
6 | # person obtaining a copy of this software and associated | ||
7 | # documentation files (the "Software"), to deal in the | ||
8 | # Software without restriction, including without limitation | ||
9 | # the rights to use, copy, modify, merge, publish, | ||
10 | # distribute, sublicense, and/or sell copies of the | ||
11 | # Software, and to permit persons to whom the Software is | ||
12 | # furnished to do so, subject to the following conditions: | ||
13 | # | ||
14 | # The above copyright notice and this permission notice | ||
15 | # shall be included in all copies or substantial portions of | ||
16 | # the Software. | ||
17 | # | ||
18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | ||
19 | # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | ||
20 | # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
21 | # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS | ||
22 | # OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
23 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
24 | # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
25 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
26 | |||
27 | from __future__ import unicode_literals | ||
28 | import codecs | ||
29 | import json | ||
30 | import os | ||
31 | |||
32 | from nikola.plugin_categories import LateTask | ||
33 | from nikola.utils import apply_filters, config_changed, copy_tree, makedirs | ||
34 | |||
35 | # This is what we need to produce: | ||
36 | # var tipuesearch = {"pages": [ | ||
37 | # {"title": "Tipue Search, a jQuery site search engine", "text": "Tipue | ||
38 | # Search is a site search engine jQuery plugin. It's free for both commercial and | ||
39 | # non-commercial use and released under the MIT License. Tipue Search includes | ||
40 | # features such as word stemming and word replacement.", "tags": "JavaScript", | ||
41 | # "loc": "http://www.tipue.com/search"}, | ||
42 | # {"title": "Tipue Search demo", "text": "Tipue Search demo. Tipue Search is | ||
43 | # a site search engine jQuery plugin.", "tags": "JavaScript", "loc": | ||
44 | # "http://www.tipue.com/search/demo"}, | ||
45 | # {"title": "About Tipue", "text": "Tipue is a small web development/design | ||
46 | # studio based in North London. We've been around for over a decade.", "tags": "", | ||
47 | # "loc": "http://www.tipue.com/about"} | ||
48 | # ]}; | ||
49 | |||
50 | |||
51 | class Tipue(LateTask): | ||
52 | """Render the blog posts as JSON data.""" | ||
53 | |||
54 | name = "localsearch" | ||
55 | |||
56 | def gen_tasks(self): | ||
57 | self.site.scan_posts() | ||
58 | |||
59 | kw = { | ||
60 | "translations": self.site.config['TRANSLATIONS'], | ||
61 | "output_folder": self.site.config['OUTPUT_FOLDER'], | ||
62 | "filters": self.site.config['FILTERS'], | ||
63 | "timeline": self.site.timeline, | ||
64 | } | ||
65 | |||
66 | posts = self.site.timeline[:] | ||
67 | dst_path = os.path.join(kw["output_folder"], "assets", "js", | ||
68 | "tipuesearch_content.js") | ||
69 | |||
70 | def save_data(): | ||
71 | pages = [] | ||
72 | for lang in kw["translations"]: | ||
73 | for post in posts: | ||
74 | # Don't index drafts (Issue #387) | ||
75 | if post.is_draft or post.is_private or post.publish_later: | ||
76 | continue | ||
77 | text = post.text(lang, strip_html=True) | ||
78 | text = text.replace('^', '') | ||
79 | |||
80 | data = {} | ||
81 | data["title"] = post.title(lang) | ||
82 | data["text"] = text | ||
83 | data["tags"] = ",".join(post.tags) | ||
84 | data["url"] = post.permalink(lang, absolute=True) | ||
85 | pages.append(data) | ||
86 | output = json.dumps({"pages": pages}, indent=2) | ||
87 | output = 'var tipuesearch = ' + output + ';' | ||
88 | makedirs(os.path.dirname(dst_path)) | ||
89 | with codecs.open(dst_path, "wb+", "utf8") as fd: | ||
90 | fd.write(output) | ||
91 | |||
92 | task = { | ||
93 | "basename": str(self.name), | ||
94 | "name": dst_path, | ||
95 | "targets": [dst_path], | ||
96 | "actions": [(save_data, [])], | ||
97 | 'uptodate': [config_changed(kw)], | ||
98 | 'calc_dep': ['_scan_locs:sitemap'] | ||
99 | } | ||
100 | yield apply_filters(task, kw['filters']) | ||
101 | |||
102 | # Copy all the assets to the right places | ||
103 | asset_folder = os.path.join(os.path.dirname(__file__), "files") | ||
104 | for task in copy_tree(asset_folder, kw["output_folder"]): | ||
105 | task["basename"] = str(self.name) | ||
106 | yield apply_filters(task, kw['filters']) | ||
diff --git a/plugins/localsearch/localsearch/__pycache__/__init__.cpython-37.pyc b/plugins/localsearch/localsearch/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 00000000..7c4aaec0 --- /dev/null +++ b/plugins/localsearch/localsearch/__pycache__/__init__.cpython-37.pyc | |||
Binary files differ | |||
diff --git a/plugins/localsearch/localsearch/files/assets/css/img/loader.gif b/plugins/localsearch/localsearch/files/assets/css/img/loader.gif new file mode 100644 index 00000000..9c97738a --- /dev/null +++ b/plugins/localsearch/localsearch/files/assets/css/img/loader.gif | |||
Binary files differ | |||
diff --git a/plugins/localsearch/localsearch/files/assets/css/img/search.png b/plugins/localsearch/localsearch/files/assets/css/img/search.png new file mode 100644 index 00000000..8c6943d4 --- /dev/null +++ b/plugins/localsearch/localsearch/files/assets/css/img/search.png | |||
Binary files differ | |||
diff --git a/plugins/localsearch/localsearch/files/assets/css/tipuesearch.css b/plugins/localsearch/localsearch/files/assets/css/tipuesearch.css new file mode 100644 index 00000000..5793c6db --- /dev/null +++ b/plugins/localsearch/localsearch/files/assets/css/tipuesearch.css | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | Tipue Search 7.1 | ||
3 | Copyright (c) 2019 Tipue | ||
4 | Tipue Search is released under the MIT License | ||
5 | http://www.tipue.com/search | ||
6 | */ | ||
7 | |||
8 | |||
9 | /* search box */ | ||
10 | |||
11 | /* | ||
12 | #tipue_search_input | ||
13 | { | ||
14 | float: left; | ||
15 | font: 15px 'Open Sans', sans-serif; | ||
16 | color: #333; | ||
17 | -webkit-font-smoothing: antialiased; | ||
18 | -moz-osx-font-smoothing: grayscale; | ||
19 | width: 230px; | ||
20 | background-color: #f3f3f3; | ||
21 | border: none; | ||
22 | padding: 9px 0 10px 18px; | ||
23 | height: 56px; | ||
24 | border-radius: 3px; | ||
25 | -moz-appearance: none; | ||
26 | -webkit-appearance: none; | ||
27 | box-sizing: border-box; | ||
28 | box-shadow: none; | ||
29 | outline: 0; | ||
30 | margin: 0; | ||
31 | } | ||
32 | #tipue_search_input:-webkit-autofill, | ||
33 | #tipue_search_input:-webkit-autofill:hover, | ||
34 | #tipue_search_input:-webkit-autofill:focus | ||
35 | { | ||
36 | -webkit-box-shadow: 0 0 0px 1000px #f3f3f3 inset; | ||
37 | } | ||
38 | */ | ||
39 | .tipue_search_button { | ||
40 | position: relative; | ||
41 | float: left; | ||
42 | width: 49px; | ||
43 | height: 56px; | ||
44 | margin-left: -3px; | ||
45 | background-color: #f3f3f3; | ||
46 | border: none; | ||
47 | border-top-right-radius: 3px; | ||
48 | border-bottom-right-radius: 3px; | ||
49 | box-sizing: border-box; | ||
50 | cursor: pointer; | ||
51 | outline: 0; | ||
52 | } | ||
53 | |||
54 | .tipue_search_icon { | ||
55 | float: left; | ||
56 | font: 24px/1 'Open Sans', sans-serif; | ||
57 | -webkit-font-smoothing: antialiased; | ||
58 | -moz-osx-font-smoothing: grayscale; | ||
59 | color: #333; | ||
60 | transform: rotate(-45deg); | ||
61 | -moz-appearance: none; | ||
62 | -webkit-appearance: none; | ||
63 | box-sizing: border-box; | ||
64 | box-shadow: none; | ||
65 | outline: 0; | ||
66 | margin: -1px 0 0 16px; | ||
67 | } | ||
68 | |||
69 | .tipue_search_group:after { | ||
70 | content: ""; | ||
71 | display: table; | ||
72 | clear: both; | ||
73 | } | ||
74 | |||
75 | |||
76 | /* search results */ | ||
77 | |||
78 | |||
79 | #tipue_search_content { | ||
80 | max-width: 100%; | ||
81 | margin: 0; | ||
82 | } | ||
83 | |||
84 | .tipue_search_content_title { | ||
85 | font-weight: 300; | ||
86 | font-size: 2rem; | ||
87 | color: #111; | ||
88 | } | ||
89 | |||
90 | .tipue_search_content_title a { | ||
91 | color: #111; | ||
92 | text-decoration: none; | ||
93 | } | ||
94 | |||
95 | .tipue_search_result { | ||
96 | padding-top: 27px; | ||
97 | } | ||
98 | |||
99 | #tipue_search_results_count, .tipue_search_content_debug { | ||
100 | font: 13px/1.5 'Source Code Pro', monospace; | ||
101 | text-transform: uppercase; | ||
102 | color: #999; | ||
103 | -webkit-font-smoothing: antialiased; | ||
104 | -moz-osx-font-smoothing: grayscale; | ||
105 | } | ||
106 | |||
107 | #tipue_search_results_count { | ||
108 | padding-top: 9px; | ||
109 | } | ||
110 | |||
111 | .tipue_search_content_url, .tipue_search_note, .tipue_search_related, #tipue_search_error, #tipue_search_replace { | ||
112 | font-weight: 300; | ||
113 | padding-top: 7px; | ||
114 | word-wrap: break-word; | ||
115 | hyphens: auto; | ||
116 | } | ||
117 | |||
118 | #tipue_search_replace, .tipue_search_related { | ||
119 | margin-top: 7px; | ||
120 | } | ||
121 | |||
122 | #tipue_search_error { | ||
123 | color: #333; | ||
124 | margin-top: 17px; | ||
125 | } | ||
126 | |||
127 | .tipue_search_content_text { | ||
128 | font-weight: 300; | ||
129 | word-wrap: break-word; | ||
130 | hyphens: auto; | ||
131 | margin-top: 9px; | ||
132 | } | ||
133 | |||
134 | .tipue_search_content_bold { | ||
135 | font-weight: 400; | ||
136 | } | ||
137 | |||
138 | .tipue_search_content_debug { | ||
139 | margin: 7px 0 2px 0; | ||
140 | } | ||
141 | |||
142 | |||
143 | /* images */ | ||
144 | |||
145 | |||
146 | .tipue_search_image { | ||
147 | padding: 17px 0 6px 0; | ||
148 | } | ||
149 | |||
150 | .tipue_search_img { | ||
151 | width: 100%; | ||
152 | max-width: 330px; | ||
153 | height: auto; | ||
154 | transition: 0.5s; | ||
155 | border-radius: 2px; | ||
156 | } | ||
157 | |||
158 | .tipue_search_img:hover { | ||
159 | opacity: 0.9; | ||
160 | } | ||
161 | |||
162 | #tipue_search_zoom_text { | ||
163 | font: 12px/1.7 'Source Code Pro', monospace; | ||
164 | color: #ccc; | ||
165 | text-transform: uppercase; | ||
166 | letter-spacing: 1px; | ||
167 | padding-top: 9px; | ||
168 | } | ||
169 | |||
170 | #tipue_search_zoom_text a { | ||
171 | color: #ccc; | ||
172 | text-decoration: none; | ||
173 | border-bottom: 2px solid #f7f7f7; | ||
174 | } | ||
175 | |||
176 | #tipue_search_zoom_text a:hover { | ||
177 | border: 0; | ||
178 | } | ||
179 | |||
180 | .tipue_search_image_zoom { | ||
181 | cursor: pointer; | ||
182 | } | ||
183 | |||
184 | #tipue_search_image_modal { | ||
185 | display: none; | ||
186 | position: fixed; | ||
187 | z-index: 1000; | ||
188 | left: 0; | ||
189 | top: 0; | ||
190 | width: 100%; | ||
191 | height: 100%; | ||
192 | overflow: auto; | ||
193 | background-color: rgba(0, 0, 0, 0.9); | ||
194 | } | ||
195 | |||
196 | .tipue_search_image_close { | ||
197 | position: absolute; | ||
198 | top: 0; | ||
199 | right: 0; | ||
200 | font: 22px/1 'Source Code Pro', monospace; | ||
201 | color: #ccc; | ||
202 | padding: 25px 30px; | ||
203 | cursor: pointer; | ||
204 | } | ||
205 | |||
206 | .tipue_search_image_block { | ||
207 | margin: 0 auto; | ||
208 | max-width: 900px; | ||
209 | padding: 73px 30px 30px 30px; | ||
210 | box-sizing: border-box; | ||
211 | color: #fff; | ||
212 | } | ||
213 | |||
214 | #tipue_search_zoom_img { | ||
215 | max-width: 100%; | ||
216 | height: auto; | ||
217 | } | ||
218 | |||
219 | #tipue_search_zoom_text, .tipue_search_zoom_options { | ||
220 | padding-top: 9px; | ||
221 | } | ||
222 | |||
223 | |||
224 | /* footer */ | ||
225 | |||
226 | |||
227 | #tipue_search_foot { | ||
228 | margin: 51px 0 21px 0; | ||
229 | } | ||
230 | |||
231 | #tipue_search_foot_boxes { | ||
232 | font: 14px 'Source Code Pro', sans-serif; | ||
233 | text-transform: uppercase; | ||
234 | color: #333; | ||
235 | padding: 0; | ||
236 | margin: 0; | ||
237 | cursor: pointer; | ||
238 | } | ||
239 | |||
240 | #tipue_search_foot_boxes li { | ||
241 | display: inline; | ||
242 | list-style: none; | ||
243 | margin: 0; | ||
244 | padding: 0; | ||
245 | } | ||
246 | |||
247 | #tipue_search_foot_boxes li a { | ||
248 | background-color: #f7f7f7; | ||
249 | color: #666; | ||
250 | padding: 10px 17px 11px 17px; | ||
251 | border-radius: 3px; | ||
252 | margin-right: 7px; | ||
253 | text-decoration: none; | ||
254 | text-align: center; | ||
255 | transition: 0.3s; | ||
256 | } | ||
257 | |||
258 | #tipue_search_foot_boxes li.current { | ||
259 | background: #252525; | ||
260 | color: #ccc; | ||
261 | padding: 10px 17px 11px 17px; | ||
262 | border-radius: 3px; | ||
263 | margin-right: 7px; | ||
264 | text-align: center; | ||
265 | } | ||
266 | |||
267 | #tipue_search_foot_boxes li a:hover { | ||
268 | background: #252525; | ||
269 | color: #ccc; | ||
270 | } | ||
271 | |||
diff --git a/plugins/localsearch/localsearch/files/assets/js/tipuesearch.js b/plugins/localsearch/localsearch/files/assets/js/tipuesearch.js new file mode 100644 index 00000000..48245668 --- /dev/null +++ b/plugins/localsearch/localsearch/files/assets/js/tipuesearch.js | |||
@@ -0,0 +1,611 @@ | |||
1 | |||
2 | /* | ||
3 | Tipue Search 7.1 | ||
4 | Copyright (c) 2019 Tipue | ||
5 | Tipue Search is released under the MIT License | ||
6 | http://www.tipue.com/search | ||
7 | */ | ||
8 | |||
9 | |||
10 | (function($) { | ||
11 | |||
12 | $.fn.tipuesearch = function(options) { | ||
13 | |||
14 | var set = $.extend( { | ||
15 | |||
16 | 'contextBuffer' : 60, | ||
17 | 'contextLength' : 60, | ||
18 | 'contextStart' : 90, | ||
19 | 'debug' : false, | ||
20 | 'descriptiveWords' : 25, | ||
21 | 'footerPages' : 3, | ||
22 | 'highlightTerms' : true, | ||
23 | 'imageZoom' : true, | ||
24 | 'minimumLength' : 3, | ||
25 | 'newWindow' : false, | ||
26 | 'show' : 10, | ||
27 | 'showContext' : true, | ||
28 | 'showRelated' : true, | ||
29 | 'showTime' : true, | ||
30 | 'showTitleCount' : true, | ||
31 | 'showURL' : true, | ||
32 | 'wholeWords' : true | ||
33 | }, options); | ||
34 | |||
35 | return this.each(function() { | ||
36 | |||
37 | var tipuesearch_t_c = 0; | ||
38 | |||
39 | var tipue_search_w = ''; | ||
40 | if (set.newWindow) | ||
41 | { | ||
42 | tipue_search_w = ' target="_blank"'; | ||
43 | } | ||
44 | |||
45 | function getURLP(name) | ||
46 | { | ||
47 | var locSearch = location.search; | ||
48 | var splitted = (new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(locSearch)||[,""]); | ||
49 | var searchString = splitted[1].replace(/\+/g, '%20'); | ||
50 | try | ||
51 | { | ||
52 | searchString = decodeURIComponent(searchString); | ||
53 | } | ||
54 | catch(e) | ||
55 | { | ||
56 | searchString = unescape(searchString); | ||
57 | } | ||
58 | return searchString || null; | ||
59 | } | ||
60 | |||
61 | if (getURLP('q')) | ||
62 | { | ||
63 | $('#tipue_search_input').val(getURLP('q')); | ||
64 | getTipueSearch(0, true); | ||
65 | } | ||
66 | |||
67 | $(this).keyup(function(event) | ||
68 | { | ||
69 | if(event.keyCode == '13') | ||
70 | { | ||
71 | getTipueSearch(0, true); | ||
72 | } | ||
73 | }); | ||
74 | |||
75 | |||
76 | function getTipueSearch(start, replace) | ||
77 | { | ||
78 | window.scrollTo(0, 0); | ||
79 | |||
80 | var out = ''; | ||
81 | var show_replace = false; | ||
82 | var show_stop = false; | ||
83 | var standard = true; | ||
84 | var c = 0; | ||
85 | var found = []; | ||
86 | |||
87 | var d_o = $('#tipue_search_input').val(); | ||
88 | d_o = d_o.replace(/\+/g, ' ').replace(/\s\s+/g, ' '); | ||
89 | |||
90 | d_o = $.trim(d_o); | ||
91 | var d = d_o.toLowerCase(); | ||
92 | |||
93 | if ((d.match("^\"") && d.match("\"$")) || (d.match("^'") && d.match("'$"))) | ||
94 | { | ||
95 | standard = false; | ||
96 | } | ||
97 | |||
98 | var d_w = d.split(' '); | ||
99 | |||
100 | if (standard) | ||
101 | { | ||
102 | d = ''; | ||
103 | for (var i = 0; i < d_w.length; i++) | ||
104 | { | ||
105 | var a_w = true; | ||
106 | for (var f = 0; f < tipuesearch_stop_words.length; f++) | ||
107 | { | ||
108 | if (d_w[i] == tipuesearch_stop_words[f]) | ||
109 | { | ||
110 | a_w = false; | ||
111 | show_stop = true; | ||
112 | } | ||
113 | } | ||
114 | if (a_w) | ||
115 | { | ||
116 | d = d + ' ' + d_w[i]; | ||
117 | } | ||
118 | } | ||
119 | d = $.trim(d); | ||
120 | d_w = d.split(' '); | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | d = d.substring(1, d.length - 1); | ||
125 | } | ||
126 | |||
127 | if (d.length >= set.minimumLength) | ||
128 | { | ||
129 | if (standard) | ||
130 | { | ||
131 | if (replace) | ||
132 | { | ||
133 | var d_r = d; | ||
134 | for (var i = 0; i < d_w.length; i++) | ||
135 | { | ||
136 | for (var f = 0; f < tipuesearch_replace.words.length; f++) | ||
137 | { | ||
138 | if (d_w[i] == tipuesearch_replace.words[f].word) | ||
139 | { | ||
140 | d = d.replace(d_w[i], tipuesearch_replace.words[f].replace_with); | ||
141 | show_replace = true; | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | d_w = d.split(' '); | ||
146 | } | ||
147 | |||
148 | var d_t = d; | ||
149 | for (var i = 0; i < d_w.length; i++) | ||
150 | { | ||
151 | for (var f = 0; f < tipuesearch_stem.words.length; f++) | ||
152 | { | ||
153 | if (d_w[i] == tipuesearch_stem.words[f].word) | ||
154 | { | ||
155 | d_t = d_t + ' ' + tipuesearch_stem.words[f].stem; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | d_w = d_t.split(' '); | ||
160 | |||
161 | for (var i = 0; i < tipuesearch.pages.length; i++) | ||
162 | { | ||
163 | var score = 0; | ||
164 | var s_t = tipuesearch.pages[i].text; | ||
165 | for (var f = 0; f < d_w.length; f++) | ||
166 | { | ||
167 | if (set.wholeWords) | ||
168 | { | ||
169 | var pat = new RegExp('\\b' + d_w[f] + '\\b', 'gi'); | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | var pat = new RegExp(d_w[f], 'gi'); | ||
174 | } | ||
175 | if (tipuesearch.pages[i].title.search(pat) != -1) | ||
176 | { | ||
177 | var m_c = tipuesearch.pages[i].title.match(pat).length; | ||
178 | score += (20 * m_c); | ||
179 | } | ||
180 | if (tipuesearch.pages[i].text.search(pat) != -1) | ||
181 | { | ||
182 | var m_c = tipuesearch.pages[i].text.match(pat).length; | ||
183 | score += (20 * m_c); | ||
184 | } | ||
185 | if (tipuesearch.pages[i].tags) | ||
186 | { | ||
187 | if (tipuesearch.pages[i].tags.search(pat) != -1) | ||
188 | { | ||
189 | var m_c = tipuesearch.pages[i].tags.match(pat).length; | ||
190 | score += (10 * m_c); | ||
191 | } | ||
192 | } | ||
193 | if (tipuesearch.pages[i].url.search(pat) != -1) | ||
194 | { | ||
195 | score += 20; | ||
196 | } | ||
197 | |||
198 | if (score != 0) | ||
199 | { | ||
200 | for (var e = 0; e < tipuesearch_weight.weight.length; e++) | ||
201 | { | ||
202 | if (tipuesearch.pages[i].url == tipuesearch_weight.weight[e].url) | ||
203 | { | ||
204 | score += tipuesearch_weight.weight[e].score; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | if (d_w[f].match('^-')) | ||
210 | { | ||
211 | pat = new RegExp(d_w[f].substring(1), 'i'); | ||
212 | if (tipuesearch.pages[i].title.search(pat) != -1 || tipuesearch.pages[i].text.search(pat) != -1 || tipuesearch.pages[i].tags.search(pat) != -1) | ||
213 | { | ||
214 | score = 0; | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | if (score != 0) | ||
220 | { | ||
221 | found.push( | ||
222 | { | ||
223 | "score": score, | ||
224 | "title": tipuesearch.pages[i].title, | ||
225 | "desc": s_t, | ||
226 | "img": tipuesearch.pages[i].img, | ||
227 | "url": tipuesearch.pages[i].url, | ||
228 | "note": tipuesearch.pages[i].note | ||
229 | }); | ||
230 | c++; | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | else | ||
235 | { | ||
236 | for (var i = 0; i < tipuesearch.pages.length; i++) | ||
237 | { | ||
238 | var score = 0; | ||
239 | var s_t = tipuesearch.pages[i].text; | ||
240 | var pat = new RegExp(d, 'gi'); | ||
241 | if (tipuesearch.pages[i].title.search(pat) != -1) | ||
242 | { | ||
243 | var m_c = tipuesearch.pages[i].title.match(pat).length; | ||
244 | score += (20 * m_c); | ||
245 | } | ||
246 | if (tipuesearch.pages[i].text.search(pat) != -1) | ||
247 | { | ||
248 | var m_c = tipuesearch.pages[i].text.match(pat).length; | ||
249 | score += (20 * m_c); | ||
250 | } | ||
251 | if (tipuesearch.pages[i].tags) | ||
252 | { | ||
253 | if (tipuesearch.pages[i].tags.search(pat) != -1) | ||
254 | { | ||
255 | var m_c = tipuesearch.pages[i].tags.match(pat).length; | ||
256 | score += (10 * m_c); | ||
257 | } | ||
258 | } | ||
259 | if (tipuesearch.pages[i].url.search(pat) != -1) | ||
260 | { | ||
261 | score += 20; | ||
262 | } | ||
263 | |||
264 | if (score != 0) | ||
265 | { | ||
266 | for (var e = 0; e < tipuesearch_weight.weight.length; e++) | ||
267 | { | ||
268 | if (tipuesearch.pages[i].url == tipuesearch_weight.weight[e].url) | ||
269 | { | ||
270 | score += tipuesearch_weight.weight[e].score; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | if (score != 0) | ||
276 | { | ||
277 | found.push( | ||
278 | { | ||
279 | "score": score, | ||
280 | "title": tipuesearch.pages[i].title, | ||
281 | "desc": s_t, | ||
282 | "img": tipuesearch.pages[i].img, | ||
283 | "url": tipuesearch.pages[i].url, | ||
284 | "note": tipuesearch.pages[i].note | ||
285 | }); | ||
286 | c++; | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | |||
291 | if (c != 0) | ||
292 | { | ||
293 | if (set.showTitleCount && tipuesearch_t_c == 0) | ||
294 | { | ||
295 | var title = document.title; | ||
296 | document.title = '(' + c + ') ' + title; | ||
297 | tipuesearch_t_c++; | ||
298 | } | ||
299 | |||
300 | if (c == 1) | ||
301 | { | ||
302 | out += '<div id="tipue_search_results_count">' + tipuesearch_string_4; | ||
303 | } | ||
304 | else | ||
305 | { | ||
306 | var c_c = c.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); | ||
307 | out += '<div id="tipue_search_results_count">' + c_c + ' ' + tipuesearch_string_5; | ||
308 | } | ||
309 | if (set.showTime) | ||
310 | { | ||
311 | var endTimer = new Date().getTime(); | ||
312 | var time = (endTimer - startTimer) / 1000; | ||
313 | out += ' (' + time.toFixed(2) + ' ' + tipuesearch_string_14 + ')'; | ||
314 | set.showTime = false; | ||
315 | } | ||
316 | out += '</div>'; | ||
317 | |||
318 | if (set.showRelated && standard) | ||
319 | { | ||
320 | var ront = ''; | ||
321 | f = 0; | ||
322 | for (var i = 0; i < tipuesearch_related.Related.length; i++) | ||
323 | { | ||
324 | if (d == tipuesearch_related.Related[i].search) | ||
325 | { | ||
326 | if (!f) | ||
327 | { | ||
328 | out += '<div class="tipue_search_related">' + tipuesearch_string_10 + ': '; | ||
329 | } | ||
330 | if (show_replace) | ||
331 | { | ||
332 | d_o = d; | ||
333 | } | ||
334 | |||
335 | if (tipuesearch_related.Related[i].include) | ||
336 | { | ||
337 | var r_d = d_o + ' ' + tipuesearch_related.Related[i].related; | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | var r_d = tipuesearch_related.Related[i].related; | ||
342 | } | ||
343 | |||
344 | ront += '<a class="tipue_search_related_btn" id="' + r_d + '">' + tipuesearch_related.Related[i].related + '</a>, '; | ||
345 | f++; | ||
346 | } | ||
347 | } | ||
348 | if (f) | ||
349 | { | ||
350 | ront = ront.slice(0, -2); | ||
351 | ront += '.</div>'; | ||
352 | out += ront; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | if (show_replace) | ||
357 | { | ||
358 | out += '<div id="tipue_search_replace">' + tipuesearch_string_2 + ' ' + d + '. ' + tipuesearch_string_3 + ' <a id="tipue_search_replaced">' + d_r + '</a></div>'; | ||
359 | } | ||
360 | |||
361 | found.sort(function(a, b) { return b.score - a.score } ); | ||
362 | |||
363 | var l_o = 0; | ||
364 | |||
365 | if (set.imageZoom) | ||
366 | { | ||
367 | out += '<div id="tipue_search_image_modal"><div class="tipue_search_image_close">✕</div><div class="tipue_search_image_block"><a id="tipue_search_zoom_url"><img id="tipue_search_zoom_img"></a><div id="tipue_search_zoom_text"></div></div></div>'; | ||
368 | } | ||
369 | |||
370 | for (var i = 0; i < found.length; i++) | ||
371 | { | ||
372 | if (l_o >= start && l_o < set.show + start) | ||
373 | { | ||
374 | out += '<div class="tipue_search_result">'; | ||
375 | |||
376 | out += '<div class="tipue_search_content_title"><a href="' + found[i].url + '"' + tipue_search_w + '>' + found[i].title + '</a></div>'; | ||
377 | |||
378 | if (set.debug) | ||
379 | { | ||
380 | out += '<div class="tipue_search_content_debug">Score: ' + found[i].score + '</div>'; | ||
381 | } | ||
382 | |||
383 | if (set.showURL) | ||
384 | { | ||
385 | var s_u = found[i].url.toLowerCase(); | ||
386 | if (s_u.indexOf('http://') == 0) | ||
387 | { | ||
388 | s_u = s_u.slice(7); | ||
389 | } | ||
390 | out += '<div class="tipue_search_content_url"><a href="' + found[i].url + '"' + tipue_search_w + '>' + s_u + '</a></div>'; | ||
391 | } | ||
392 | |||
393 | if (found[i].img) | ||
394 | { | ||
395 | if (set.imageZoom) | ||
396 | { | ||
397 | out += '<div class="tipue_search_image"><img class="tipue_search_img tipue_search_image_zoom" src="' + found[i].img + '" alt="' + found[i].title + '" data-url="' + found[i].url + '"></div>'; | ||
398 | } | ||
399 | else | ||
400 | { | ||
401 | out += '<div class="tipue_search_image"><a href="' + found[i].url + '"' + tipue_search_w + '><img class="tipue_search_img" src="' + found[i].img + '" alt="' + found[i].title + '"></a></div>'; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | if (found[i].desc) | ||
406 | { | ||
407 | var t = found[i].desc; | ||
408 | |||
409 | if (set.showContext) | ||
410 | { | ||
411 | d_w = d.split(' '); | ||
412 | var s_1 = found[i].desc.toLowerCase().indexOf(d_w[0]); | ||
413 | if (s_1 > set.contextStart) | ||
414 | { | ||
415 | var t_1 = t.substr(s_1 - set.contextBuffer); | ||
416 | var s_2 = t_1.indexOf(' '); | ||
417 | t_1 = t.substr(s_1 - set.contextBuffer + s_2); | ||
418 | t_1 = $.trim(t_1); | ||
419 | |||
420 | if (t_1.length > set.contextLength) | ||
421 | { | ||
422 | t = '... ' + t_1; | ||
423 | } | ||
424 | } | ||
425 | } | ||
426 | |||
427 | if (standard) | ||
428 | { | ||
429 | d_w = d.split(' '); | ||
430 | for (var f = 0; f < d_w.length; f++) | ||
431 | { | ||
432 | if (set.highlightTerms) | ||
433 | { | ||
434 | var patr = new RegExp('(' + d_w[f] + ')', 'gi'); | ||
435 | t = t.replace(patr, "<h0011>$1<h0012>"); | ||
436 | } | ||
437 | } | ||
438 | } | ||
439 | else if (set.highlightTerms) | ||
440 | { | ||
441 | var patr = new RegExp('(' + d + ')', 'gi'); | ||
442 | t = t.replace(patr, "<span class=\"tipue_search_content_bold\">$1</span>"); | ||
443 | } | ||
444 | |||
445 | var t_d = ''; | ||
446 | var t_w = t.split(' '); | ||
447 | if (t_w.length < set.descriptiveWords) | ||
448 | { | ||
449 | t_d = t; | ||
450 | } | ||
451 | else | ||
452 | { | ||
453 | for (var f = 0; f < set.descriptiveWords; f++) | ||
454 | { | ||
455 | t_d += t_w[f] + ' '; | ||
456 | } | ||
457 | } | ||
458 | t_d = $.trim(t_d); | ||
459 | if (t_d.charAt(t_d.length - 1) != '.') | ||
460 | { | ||
461 | t_d += ' ...'; | ||
462 | } | ||
463 | |||
464 | t_d = t_d.replace(/h0011/g, 'span class=\"tipue_search_content_bold\"'); | ||
465 | t_d = t_d.replace(/h0012/g, '/span'); | ||
466 | |||
467 | out += '<div class="tipue_search_content_text">' + t_d + '</div>'; | ||
468 | } | ||
469 | |||
470 | if (found[i].note) | ||
471 | { | ||
472 | out += '<div class="tipue_search_note">' + found[i].note + '</div>'; | ||
473 | } | ||
474 | |||
475 | out += '</div>'; | ||
476 | } | ||
477 | l_o++; | ||
478 | } | ||
479 | |||
480 | if (c > set.show) | ||
481 | { | ||
482 | var pages = Math.ceil(c / set.show); | ||
483 | var page = (start / set.show); | ||
484 | if (set.footerPages < 3) | ||
485 | { | ||
486 | set.footerPages = 3; | ||
487 | } | ||
488 | |||
489 | out += '<div id="tipue_search_foot"><ul id="tipue_search_foot_boxes">'; | ||
490 | |||
491 | if (start > 0) | ||
492 | { | ||
493 | out += '<li role="navigation"><a class="tipue_search_foot_box" accesskey="b" id="' + (start - set.show) + '_' + replace + '">' + tipuesearch_string_6 + '</a></li>'; | ||
494 | } | ||
495 | |||
496 | if (page <= 2) | ||
497 | { | ||
498 | var p_b = pages; | ||
499 | if (pages > set.footerPages) | ||
500 | { | ||
501 | p_b = set.footerPages; | ||
502 | } | ||
503 | for (var f = 0; f < p_b; f++) | ||
504 | { | ||
505 | if (f == page) | ||
506 | { | ||
507 | out += '<li class="current" role="navigation">' + (f + 1) + '</li>'; | ||
508 | } | ||
509 | else | ||
510 | { | ||
511 | out += '<li role="navigation"><a class="tipue_search_foot_box" id="' + (f * set.show) + '_' + replace + '">' + (f + 1) + '</a></li>'; | ||
512 | } | ||
513 | } | ||
514 | } | ||
515 | else | ||
516 | { | ||
517 | var p_b = page + set.footerPages - 1; | ||
518 | if (p_b > pages) | ||
519 | { | ||
520 | p_b = pages; | ||
521 | } | ||
522 | for (var f = page - 1; f < p_b; f++) | ||
523 | { | ||
524 | if (f == page) | ||
525 | { | ||
526 | out += '<li class="current" role="navigation">' + (f + 1) + '</li>'; | ||
527 | } | ||
528 | else | ||
529 | { | ||
530 | out += '<li role="navigation"><a class="tipue_search_foot_box" id="' + (f * set.show) + '_' + replace + '">' + (f + 1) + '</a></li>'; | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | |||
535 | if (page + 1 != pages) | ||
536 | { | ||
537 | out += '<li role="navigation"><a class="tipue_search_foot_box" accesskey="m" id="' + (start + set.show) + '_' + replace + '">' + tipuesearch_string_7 + '</a></li>'; | ||
538 | } | ||
539 | |||
540 | out += '</ul></div>'; | ||
541 | } | ||
542 | |||
543 | } | ||
544 | else | ||
545 | { | ||
546 | out += '<div id="tipue_search_error">' + tipuesearch_string_8 + '</div>'; | ||
547 | } | ||
548 | } | ||
549 | else | ||
550 | { | ||
551 | if (show_stop) | ||
552 | { | ||
553 | out += '<div id="tipue_search_error">' + tipuesearch_string_8 + ' ' + tipuesearch_string_9 + '</div>'; | ||
554 | } | ||
555 | else | ||
556 | { | ||
557 | if (set.minimumLength == 1) | ||
558 | { | ||
559 | out += '<div id="tipue_search_error">' + tipuesearch_string_11 + '</div>'; | ||
560 | } | ||
561 | else | ||
562 | { | ||
563 | out += '<div id="tipue_search_error">' + tipuesearch_string_12 + ' ' + set.minimumLength + ' ' + tipuesearch_string_13 + '</div>'; | ||
564 | } | ||
565 | } | ||
566 | } | ||
567 | |||
568 | $('#tipue_search_content').hide().html(out).slideDown(200); | ||
569 | |||
570 | $('#tipue_search_replaced').click(function() | ||
571 | { | ||
572 | getTipueSearch(0, false); | ||
573 | }); | ||
574 | |||
575 | $('.tipue_search_related_btn').click(function() | ||
576 | { | ||
577 | $('#tipue_search_input').val($(this).attr('id')); | ||
578 | getTipueSearch(0, true); | ||
579 | }); | ||
580 | |||
581 | $('.tipue_search_image_zoom').click(function() | ||
582 | { | ||
583 | $('#tipue_search_image_modal').fadeIn(300); | ||
584 | $('#tipue_search_zoom_img').attr('src', this.src); | ||
585 | |||
586 | var z_u = $(this).attr('data-url'); | ||
587 | $('#tipue_search_zoom_url').attr('href', z_u); | ||
588 | |||
589 | var z_o = this.alt + '<div class="tipue_search_zoom_options"><a href="' + this.src + '" target="_blank">' + tipuesearch_string_15 + '</a> <a href="' + z_u + '">' + tipuesearch_string_16 + '</a></div>'; | ||
590 | |||
591 | $('#tipue_search_zoom_text').html(z_o); | ||
592 | }); | ||
593 | |||
594 | $('.tipue_search_image_close').click(function() | ||
595 | { | ||
596 | $('#tipue_search_image_modal').fadeOut(300); | ||
597 | }); | ||
598 | |||
599 | $('.tipue_search_foot_box').click(function() | ||
600 | { | ||
601 | var id_v = $(this).attr('id'); | ||
602 | var id_a = id_v.split('_'); | ||
603 | |||
604 | getTipueSearch(parseInt(id_a[0]), id_a[1]); | ||
605 | }); | ||
606 | } | ||
607 | |||
608 | }); | ||
609 | }; | ||
610 | |||
611 | })(jQuery); | ||
diff --git a/plugins/localsearch/localsearch/files/assets/js/tipuesearch.min.js b/plugins/localsearch/localsearch/files/assets/js/tipuesearch.min.js new file mode 100644 index 00000000..f50ef6ee --- /dev/null +++ b/plugins/localsearch/localsearch/files/assets/js/tipuesearch.min.js | |||
@@ -0,0 +1,181 @@ | |||
1 | (function($){$.fn.tipuesearch=function(options){var set=$.extend({'contextBuffer':60,'contextLength':60,'contextStart':90,'debug':false,'descriptiveWords':25,'footerPages':3,'highlightTerms':true,'imageZoom':true,'minimumLength':3,'newWindow':false,'show':10,'showContext':true,'showRelated':true,'showTime':true,'showTitleCount':true,'showURL':true,'wholeWords':true},options);return this.each(function(){var tipuesearch_t_c=0;var tipue_search_w='';if(set.newWindow) | ||
2 | {tipue_search_w=' target="_blank"';} | ||
3 | function getURLP(name) | ||
4 | {var locSearch=location.search;var splitted=(new RegExp('[?|&]'+name+'='+'([^&;]+?)(&|#|;|$)').exec(locSearch)||[,""]);var searchString=splitted[1].replace(/\+/g,'%20');try | ||
5 | {searchString=decodeURIComponent(searchString);} | ||
6 | catch(e) | ||
7 | {searchString=unescape(searchString);} | ||
8 | return searchString||null;} | ||
9 | if(getURLP('q')) | ||
10 | {$('#tipue_search_input').val(getURLP('q'));getTipueSearch(0,true);} | ||
11 | $(this).keyup(function(event) | ||
12 | {if(event.keyCode=='13') | ||
13 | {getTipueSearch(0,true);}});function getTipueSearch(start,replace) | ||
14 | {window.scrollTo(0,0);var out='';var show_replace=false;var show_stop=false;var standard=true;var c=0;var found=[];var d_o=$('#tipue_search_input').val();d_o=d_o.replace(/\+/g,' ').replace(/\s\s+/g,' ');d_o=$.trim(d_o);var d=d_o.toLowerCase();if((d.match("^\"")&&d.match("\"$"))||(d.match("^'")&&d.match("'$"))) | ||
15 | {standard=false;} | ||
16 | var d_w=d.split(' ');if(standard) | ||
17 | {d='';for(var i=0;i<d_w.length;i++) | ||
18 | {var a_w=true;for(var f=0;f<tipuesearch_stop_words.length;f++) | ||
19 | {if(d_w[i]==tipuesearch_stop_words[f]) | ||
20 | {a_w=false;show_stop=true;}} | ||
21 | if(a_w) | ||
22 | {d=d+' '+d_w[i];}} | ||
23 | d=$.trim(d);d_w=d.split(' ');} | ||
24 | else | ||
25 | {d=d.substring(1,d.length-1);} | ||
26 | if(d.length>=set.minimumLength) | ||
27 | {if(standard) | ||
28 | {if(replace) | ||
29 | {var d_r=d;for(var i=0;i<d_w.length;i++) | ||
30 | {for(var f=0;f<tipuesearch_replace.words.length;f++) | ||
31 | {if(d_w[i]==tipuesearch_replace.words[f].word) | ||
32 | {d=d.replace(d_w[i],tipuesearch_replace.words[f].replace_with);show_replace=true;}}} | ||
33 | d_w=d.split(' ');} | ||
34 | var d_t=d;for(var i=0;i<d_w.length;i++) | ||
35 | {for(var f=0;f<tipuesearch_stem.words.length;f++) | ||
36 | {if(d_w[i]==tipuesearch_stem.words[f].word) | ||
37 | {d_t=d_t+' '+tipuesearch_stem.words[f].stem;}}} | ||
38 | d_w=d_t.split(' ');for(var i=0;i<tipuesearch.pages.length;i++) | ||
39 | {var score=0;var s_t=tipuesearch.pages[i].text;for(var f=0;f<d_w.length;f++) | ||
40 | {if(set.wholeWords) | ||
41 | {var pat=new RegExp('\\b'+d_w[f]+'\\b','gi');} | ||
42 | else | ||
43 | {var pat=new RegExp(d_w[f],'gi');} | ||
44 | if(tipuesearch.pages[i].title.search(pat)!=-1) | ||
45 | {var m_c=tipuesearch.pages[i].title.match(pat).length;score+=(20*m_c);} | ||
46 | if(tipuesearch.pages[i].text.search(pat)!=-1) | ||
47 | {var m_c=tipuesearch.pages[i].text.match(pat).length;score+=(20*m_c);} | ||
48 | if(tipuesearch.pages[i].tags) | ||
49 | {if(tipuesearch.pages[i].tags.search(pat)!=-1) | ||
50 | {var m_c=tipuesearch.pages[i].tags.match(pat).length;score+=(10*m_c);}} | ||
51 | if(tipuesearch.pages[i].url.search(pat)!=-1) | ||
52 | {score+=20;} | ||
53 | if(score!=0) | ||
54 | {for(var e=0;e<tipuesearch_weight.weight.length;e++) | ||
55 | {if(tipuesearch.pages[i].url==tipuesearch_weight.weight[e].url) | ||
56 | {score+=tipuesearch_weight.weight[e].score;}}} | ||
57 | if(d_w[f].match('^-')) | ||
58 | {pat=new RegExp(d_w[f].substring(1),'i');if(tipuesearch.pages[i].title.search(pat)!=-1||tipuesearch.pages[i].text.search(pat)!=-1||tipuesearch.pages[i].tags.search(pat)!=-1) | ||
59 | {score=0;}}} | ||
60 | if(score!=0) | ||
61 | {found.push({"score":score,"title":tipuesearch.pages[i].title,"desc":s_t,"img":tipuesearch.pages[i].img,"url":tipuesearch.pages[i].url,"note":tipuesearch.pages[i].note});c++;}}} | ||
62 | else | ||
63 | {for(var i=0;i<tipuesearch.pages.length;i++) | ||
64 | {var score=0;var s_t=tipuesearch.pages[i].text;var pat=new RegExp(d,'gi');if(tipuesearch.pages[i].title.search(pat)!=-1) | ||
65 | {var m_c=tipuesearch.pages[i].title.match(pat).length;score+=(20*m_c);} | ||
66 | if(tipuesearch.pages[i].text.search(pat)!=-1) | ||
67 | {var m_c=tipuesearch.pages[i].text.match(pat).length;score+=(20*m_c);} | ||
68 | if(tipuesearch.pages[i].tags) | ||
69 | {if(tipuesearch.pages[i].tags.search(pat)!=-1) | ||
70 | {var m_c=tipuesearch.pages[i].tags.match(pat).length;score+=(10*m_c);}} | ||
71 | if(tipuesearch.pages[i].url.search(pat)!=-1) | ||
72 | {score+=20;} | ||
73 | if(score!=0) | ||
74 | {for(var e=0;e<tipuesearch_weight.weight.length;e++) | ||
75 | {if(tipuesearch.pages[i].url==tipuesearch_weight.weight[e].url) | ||
76 | {score+=tipuesearch_weight.weight[e].score;}}} | ||
77 | if(score!=0) | ||
78 | {found.push({"score":score,"title":tipuesearch.pages[i].title,"desc":s_t,"img":tipuesearch.pages[i].img,"url":tipuesearch.pages[i].url,"note":tipuesearch.pages[i].note});c++;}}} | ||
79 | if(c!=0) | ||
80 | {if(set.showTitleCount&&tipuesearch_t_c==0) | ||
81 | {var title=document.title;document.title='('+c+') '+title;tipuesearch_t_c++;} | ||
82 | if(c==1) | ||
83 | {out+='<div id="tipue_search_results_count">'+tipuesearch_string_4;} | ||
84 | else | ||
85 | {var c_c=c.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",");out+='<div id="tipue_search_results_count">'+c_c+' '+tipuesearch_string_5;} | ||
86 | if(set.showTime) | ||
87 | {var endTimer=new Date().getTime();var time=(endTimer-startTimer)/ 1000;out+=' ('+time.toFixed(2)+' '+tipuesearch_string_14+')';set.showTime=false;} | ||
88 | out+='</div>';if(set.showRelated&&standard) | ||
89 | {var ront='';f=0;for(var i=0;i<tipuesearch_related.Related.length;i++) | ||
90 | {if(d==tipuesearch_related.Related[i].search) | ||
91 | {if(!f) | ||
92 | {out+='<div class="tipue_search_related">'+tipuesearch_string_10+': ';} | ||
93 | if(show_replace) | ||
94 | {d_o=d;} | ||
95 | if(tipuesearch_related.Related[i].include) | ||
96 | {var r_d=d_o+' '+tipuesearch_related.Related[i].related;} | ||
97 | else | ||
98 | {var r_d=tipuesearch_related.Related[i].related;} | ||
99 | ront+='<a class="tipue_search_related_btn" id="'+r_d+'">'+tipuesearch_related.Related[i].related+'</a>, ';f++;}} | ||
100 | if(f) | ||
101 | {ront=ront.slice(0,-2);ront+='.</div>';out+=ront;}} | ||
102 | if(show_replace) | ||
103 | {out+='<div id="tipue_search_replace">'+tipuesearch_string_2+' '+d+'. '+tipuesearch_string_3+' <a id="tipue_search_replaced">'+d_r+'</a></div>';} | ||
104 | found.sort(function(a,b){return b.score-a.score});var l_o=0;if(set.imageZoom) | ||
105 | {out+='<div id="tipue_search_image_modal"><div class="tipue_search_image_close">✕</div><div class="tipue_search_image_block"><a id="tipue_search_zoom_url"><img id="tipue_search_zoom_img"></a><div id="tipue_search_zoom_text"></div></div></div>';} | ||
106 | for(var i=0;i<found.length;i++) | ||
107 | {if(l_o>=start&&l_o<set.show+start) | ||
108 | {out+='<div class="tipue_search_result">';out+='<div class="tipue_search_content_title"><a href="'+found[i].url+'"'+tipue_search_w+'>'+found[i].title+'</a></div>';if(set.debug) | ||
109 | {out+='<div class="tipue_search_content_debug">Score: '+found[i].score+'</div>';} | ||
110 | if(set.showURL) | ||
111 | {var s_u=found[i].url.toLowerCase();if(s_u.indexOf('http://')==0) | ||
112 | {s_u=s_u.slice(7);} | ||
113 | out+='<div class="tipue_search_content_url"><a href="'+found[i].url+'"'+tipue_search_w+'>'+s_u+'</a></div>';} | ||
114 | if(found[i].img) | ||
115 | {if(set.imageZoom) | ||
116 | {out+='<div class="tipue_search_image"><img class="tipue_search_img tipue_search_image_zoom" src="'+found[i].img+'" alt="'+found[i].title+'" data-url="'+found[i].url+'"></div>';} | ||
117 | else | ||
118 | {out+='<div class="tipue_search_image"><a href="'+found[i].url+'"'+tipue_search_w+'><img class="tipue_search_img" src="'+found[i].img+'" alt="'+found[i].title+'"></a></div>';}} | ||
119 | if(found[i].desc) | ||
120 | {var t=found[i].desc;if(set.showContext) | ||
121 | {d_w=d.split(' ');var s_1=found[i].desc.toLowerCase().indexOf(d_w[0]);if(s_1>set.contextStart) | ||
122 | {var t_1=t.substr(s_1-set.contextBuffer);var s_2=t_1.indexOf(' ');t_1=t.substr(s_1-set.contextBuffer+s_2);t_1=$.trim(t_1);if(t_1.length>set.contextLength) | ||
123 | {t='... '+t_1;}}} | ||
124 | if(standard) | ||
125 | {d_w=d.split(' ');for(var f=0;f<d_w.length;f++) | ||
126 | {if(set.highlightTerms) | ||
127 | {var patr=new RegExp('('+d_w[f]+')','gi');t=t.replace(patr,"<h0011>$1<h0012>");}}} | ||
128 | else if(set.highlightTerms) | ||
129 | {var patr=new RegExp('('+d+')','gi');t=t.replace(patr,"<span class=\"tipue_search_content_bold\">$1</span>");} | ||
130 | var t_d='';var t_w=t.split(' ');if(t_w.length<set.descriptiveWords) | ||
131 | {t_d=t;} | ||
132 | else | ||
133 | {for(var f=0;f<set.descriptiveWords;f++) | ||
134 | {t_d+=t_w[f]+' ';}} | ||
135 | t_d=$.trim(t_d);if(t_d.charAt(t_d.length-1)!='.') | ||
136 | {t_d+=' ...';} | ||
137 | t_d=t_d.replace(/h0011/g,'span class=\"tipue_search_content_bold\"');t_d=t_d.replace(/h0012/g,'/span');out+='<div class="tipue_search_content_text">'+t_d+'</div>';} | ||
138 | if(found[i].note) | ||
139 | {out+='<div class="tipue_search_note">'+found[i].note+'</div>';} | ||
140 | out+='</div>';} | ||
141 | l_o++;} | ||
142 | if(c>set.show) | ||
143 | {var pages=Math.ceil(c / set.show);var page=(start / set.show);if(set.footerPages<3) | ||
144 | {set.footerPages=3;} | ||
145 | out+='<div id="tipue_search_foot"><ul id="tipue_search_foot_boxes">';if(start>0) | ||
146 | {out+='<li role="navigation"><a class="tipue_search_foot_box" accesskey="b" id="'+(start-set.show)+'_'+replace+'">'+tipuesearch_string_6+'</a></li>';} | ||
147 | if(page<=2) | ||
148 | {var p_b=pages;if(pages>set.footerPages) | ||
149 | {p_b=set.footerPages;} | ||
150 | for(var f=0;f<p_b;f++) | ||
151 | {if(f==page) | ||
152 | {out+='<li class="current" role="navigation">'+(f+1)+'</li>';} | ||
153 | else | ||
154 | {out+='<li role="navigation"><a class="tipue_search_foot_box" id="'+(f*set.show)+'_'+replace+'">'+(f+1)+'</a></li>';}}} | ||
155 | else | ||
156 | {var p_b=page+set.footerPages-1;if(p_b>pages) | ||
157 | {p_b=pages;} | ||
158 | for(var f=page-1;f<p_b;f++) | ||
159 | {if(f==page) | ||
160 | {out+='<li class="current" role="navigation">'+(f+1)+'</li>';} | ||
161 | else | ||
162 | {out+='<li role="navigation"><a class="tipue_search_foot_box" id="'+(f*set.show)+'_'+replace+'">'+(f+1)+'</a></li>';}}} | ||
163 | if(page+1!=pages) | ||
164 | {out+='<li role="navigation"><a class="tipue_search_foot_box" accesskey="m" id="'+(start+set.show)+'_'+replace+'">'+tipuesearch_string_7+'</a></li>';} | ||
165 | out+='</ul></div>';}} | ||
166 | else | ||
167 | {out+='<div id="tipue_search_error">'+tipuesearch_string_8+'</div>';}} | ||
168 | else | ||
169 | {if(show_stop) | ||
170 | {out+='<div id="tipue_search_error">'+tipuesearch_string_8+' '+tipuesearch_string_9+'</div>';} | ||
171 | else | ||
172 | {if(set.minimumLength==1) | ||
173 | {out+='<div id="tipue_search_error">'+tipuesearch_string_11+'</div>';} | ||
174 | else | ||
175 | {out+='<div id="tipue_search_error">'+tipuesearch_string_12+' '+set.minimumLength+' '+tipuesearch_string_13+'</div>';}}} | ||
176 | $('#tipue_search_content').hide().html(out).slideDown(200);$('#tipue_search_replaced').click(function() | ||
177 | {getTipueSearch(0,false);});$('.tipue_search_related_btn').click(function() | ||
178 | {$('#tipue_search_input').val($(this).attr('id'));getTipueSearch(0,true);});$('.tipue_search_image_zoom').click(function() | ||
179 | {$('#tipue_search_image_modal').fadeIn(300);$('#tipue_search_zoom_img').attr('src',this.src);var z_u=$(this).attr('data-url');$('#tipue_search_zoom_url').attr('href',z_u);var z_o=this.alt+'<div class="tipue_search_zoom_options"><a href="'+this.src+'" target="_blank">'+tipuesearch_string_15+'</a> <a href="'+z_u+'">'+tipuesearch_string_16+'</a></div>';$('#tipue_search_zoom_text').html(z_o);});$('.tipue_search_image_close').click(function() | ||
180 | {$('#tipue_search_image_modal').fadeOut(300);});$('.tipue_search_foot_box').click(function() | ||
181 | {var id_v=$(this).attr('id');var id_a=id_v.split('_');getTipueSearch(parseInt(id_a[0]),id_a[1]);});}});};})(jQuery); \ No newline at end of file | ||
diff --git a/plugins/localsearch/localsearch/files/assets/js/tipuesearch_set.js b/plugins/localsearch/localsearch/files/assets/js/tipuesearch_set.js new file mode 100644 index 00000000..8475b5c0 --- /dev/null +++ b/plugins/localsearch/localsearch/files/assets/js/tipuesearch_set.js | |||
@@ -0,0 +1,84 @@ | |||
1 | |||
2 | /* | ||
3 | Tipue Search 7.1 | ||
4 | Copyright (c) 2019 Tipue | ||
5 | Tipue Search is released under the MIT License | ||
6 | http://www.tipue.com/search | ||
7 | */ | ||
8 | |||
9 | |||
10 | /* | ||
11 | Stop words | ||
12 | Stop words list from http://www.ranks.nl/stopwords | ||
13 | */ | ||
14 | |||
15 | var tipuesearch_stop_words = ["a", "about", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "aren't", "as", "at", "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "can't", "cannot", "could", "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "don't", "down", "during", "each", "few", "for", "from", "further", "had", "hadn't", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "he's", "her", "here", "here's", "hers", "herself", "him", "himself", "his", "how", "how's", "i", "i'd", "i'll", "i'm", "i've", "if", "in", "into", "is", "isn't", "it", "it's", "its", "itself", "let's", "me", "more", "most", "mustn't", "my", "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours", "ourselves", "out", "over", "own", "same", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "so", "some", "such", "than", "that", "that's", "the", "their", "theirs", "them", "themselves", "then", "there", "there's", "these", "they", "they'd", "they'll", "they're", "they've", "this", "those", "through", "to", "too", "under", "until", "up", "very", "was", "wasn't", "we", "we'd", "we'll", "we're", "we've", "were", "weren't", "what", "what's", "when", "when's", "where", "where's", "which", "while", "who", "who's", "whom", "why", "why's", "with", "won't", "would", "wouldn't", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves"]; | ||
16 | |||
17 | |||
18 | // Word replace | ||
19 | |||
20 | var tipuesearch_replace = {'words': [ | ||
21 | {'word': 'tipua', 'replace_with': 'tipue'}, | ||
22 | {'word': 'javscript', 'replace_with': 'javascript'}, | ||
23 | {'word': 'jqeury', 'replace_with': 'jquery'} | ||
24 | ]}; | ||
25 | |||
26 | |||
27 | // Weighting | ||
28 | |||
29 | var tipuesearch_weight = {'weight': [ | ||
30 | {'url': 'http://www.tipue.com', 'score': 60}, | ||
31 | {'url': 'http://www.tipue.com/search', 'score': 60}, | ||
32 | {'url': 'http://www.tipue.com/tipr', 'score': 30}, | ||
33 | {'url': 'http://www.tipue.com/support', 'score': 20} | ||
34 | ]}; | ||
35 | |||
36 | |||
37 | // Illogical stemming | ||
38 | |||
39 | var tipuesearch_stem = {'words': [ | ||
40 | {'word': 'e-mail', 'stem': 'email'}, | ||
41 | {'word': 'javascript', 'stem': 'jquery'}, | ||
42 | {'word': 'javascript', 'stem': 'js'} | ||
43 | ]}; | ||
44 | |||
45 | |||
46 | // Related | ||
47 | |||
48 | var tipuesearch_related = {'Related': [ | ||
49 | {'search': 'tipue', 'related': 'Search', 'include': 1}, | ||
50 | {'search': 'tipue', 'related': 'jQuery'}, | ||
51 | {'search': 'tipue', 'related': 'Blog'}, | ||
52 | {'search': 'tipue', 'related': 'Support'}, | ||
53 | {'search': 'tipue search', 'related': 'Demo', 'include': 1}, | ||
54 | {'search': 'tipue search', 'related': 'Support'} | ||
55 | ]}; | ||
56 | |||
57 | |||
58 | // Internal strings | ||
59 | |||
60 | var tipuesearch_string_1 = 'No title'; | ||
61 | var tipuesearch_string_2 = 'Showing results for'; | ||
62 | var tipuesearch_string_3 = 'Search instead for'; | ||
63 | var tipuesearch_string_4 = '1 result'; | ||
64 | var tipuesearch_string_5 = 'results'; | ||
65 | var tipuesearch_string_6 = 'Prev'; | ||
66 | var tipuesearch_string_7 = 'Next'; | ||
67 | var tipuesearch_string_8 = 'Nothing found'; | ||
68 | var tipuesearch_string_9 = 'Common words are largely ignored'; | ||
69 | var tipuesearch_string_10 = 'Related'; | ||
70 | var tipuesearch_string_11 = 'Search should be one character or more'; | ||
71 | var tipuesearch_string_12 = 'Search should be'; | ||
72 | var tipuesearch_string_13 = 'characters or more'; | ||
73 | var tipuesearch_string_14 = 'seconds'; | ||
74 | var tipuesearch_string_15 = 'Open Image'; | ||
75 | var tipuesearch_string_16 = 'Goto Page'; | ||
76 | |||
77 | |||
78 | // Internals | ||
79 | |||
80 | |||
81 | // Timer for showTime | ||
82 | |||
83 | var startTimer = new Date().getTime(); | ||
84 | |||
diff --git a/plugins/localsearch/localsearch/templates/jinja/localsearch.tmpl b/plugins/localsearch/localsearch/templates/jinja/localsearch.tmpl new file mode 100644 index 00000000..d392782e --- /dev/null +++ b/plugins/localsearch/localsearch/templates/jinja/localsearch.tmpl | |||
@@ -0,0 +1,20 @@ | |||
1 | {# -*- coding: utf-8 -*- #} | ||
2 | {% extends 'base.tmpl' %} | ||
3 | {% block content %} | ||
4 | <h1>Search</h1> | ||
5 | <noscript>Search requires JavaScript, sorry for the inconvenience.</noscript> | ||
6 | <div id="tipue_search_content">Use the search box in the navigation bar to search.</div> | ||
7 | {% endblock %} | ||
8 | |||
9 | {% block extra_js %} | ||
10 | <script src="/assets/js/tipuesearch_set.js"></script> | ||
11 | <script src="/assets/js/tipuesearch.js"></script> | ||
12 | <script src="/assets/js/tipuesearch_content.js"></script> | ||
13 | <script> | ||
14 | $(document).ready(function() { | ||
15 | $('#tipue_search_input').tipuesearch({ | ||
16 | 'showUrl': false | ||
17 | }); | ||
18 | }); | ||
19 | </script> | ||
20 | {% endblock %} | ||
diff --git a/plugins/localsearch/localsearch/templates/mako/localsearch.tmpl b/plugins/localsearch/localsearch/templates/mako/localsearch.tmpl new file mode 100644 index 00000000..38441904 --- /dev/null +++ b/plugins/localsearch/localsearch/templates/mako/localsearch.tmpl | |||
@@ -0,0 +1,20 @@ | |||
1 | ## -*- coding: utf-8 -*- | ||
2 | <%inherit file="base.tmpl"/> | ||
3 | <%block name="content"> | ||
4 | <h1>Search</h1> | ||
5 | <noscript>Search requires JavaScript, sorry for the inconvenience.</noscript> | ||
6 | <div id="tipue_search_content">Use the search box in the navigation bar to search.</div> | ||
7 | </%block> | ||
8 | |||
9 | <%block name="extra_js"> | ||
10 | <script src="/assets/js/tipuesearch_set.js"></script> | ||
11 | <script src="/assets/js/tipuesearch.js"></script> | ||
12 | <script src="/assets/js/tipuesearch_content.js"></script> | ||
13 | <script> | ||
14 | $(document).ready(function() { | ||
15 | $('#tipue_search_input').tipuesearch({ | ||
16 | 'showUrl': false | ||
17 | }); | ||
18 | }); | ||
19 | </script> | ||
20 | </%block> | ||
diff --git a/plugins/localsearch/search-EXAMPLE.html b/plugins/localsearch/search-EXAMPLE.html new file mode 100644 index 00000000..f8970bc5 --- /dev/null +++ b/plugins/localsearch/search-EXAMPLE.html | |||
@@ -0,0 +1,13 @@ | |||
1 | <!-- | ||
2 | .. title: Search | ||
3 | .. slug: search | ||
4 | .. date: 1970-01-01 00:00:00Z | ||
5 | .. tags: | ||
6 | .. category: | ||
7 | .. link: | ||
8 | .. description: | ||
9 | .. type: text | ||
10 | .. template: localsearch.tmpl | ||
11 | --> | ||
12 | |||
13 | <p style="display: none;">Search results appear here.</p> | ||