diff --git a/orcinus/admin.php b/orcinus/admin.php index d4a28f3..e8f99eb 100644 --- a/orcinus/admin.php +++ b/orcinus/admin.php @@ -846,6 +846,29 @@ if (!$_SESSION['admin_username']) { } else $_POST['os_s_show_filetype_html'] = 0; OS_setValue('s_show_filetype_html', $_POST['os_s_show_filetype_html']); + if (isset($_POST['os_s_text_fragments']) && $_POST['os_s_text_fragments'] == '1') { + $_POST['os_s_text_fragments'] = 1; + if (strpos($_ODATA['s_result_template'], ' href="{{url}}" rel="noopener" ') === false) { + OS_setValue('s_result_template', str_replace( + ' href="{{url}}" ', + ' href="{{url}}" rel="noopener" ', + $_ODATA['s_result_template'] + )); + $_SESSION['message'][] = <<rel="noopener" has been added to the links in your result template. +More info... +ORCINUS; + } + } else { + $_POST['os_s_text_fragments'] = 0; + OS_setValue('s_result_template', str_replace( + ' href="{{url}}" rel="noopener" ', + ' href="{{url}}" ', + $_ODATA['s_result_template'] + )); + } + OS_setValue('s_text_fragments', $_POST['os_s_text_fragments']); + $_SESSION['message'][] = 'Search settings have been saved.'; break; @@ -1004,6 +1027,7 @@ if (!$_SESSION['admin_username']) { 's_limit_term_length' => $_ODATA['s_limit_term_length'], 's_limit_matchtext' => $_ODATA['s_limit_matchtext'], 's_show_filetype_html' => $_ODATA['s_show_filetype_html'], + 's_text_fragments' => $_ODATA['s_text_fragments'], 's_results_pagination' => $_ODATA['s_results_pagination'], 's_limit_results' => $_ODATA['s_limit_results'], 's_result_template' => json_encode(preg_replace('/\s{2,}/', ' ', $_ODATA['s_result_template']), JSON_INVALID_UTF8_IGNORE), @@ -1360,7 +1384,7 @@ if (!$_SESSION['admin_username']) { while ($error = array_shift($_SESSION['error'])) { ?>
> +
  • + > + +
  • diff --git a/orcinus/config.php b/orcinus/config.php index 86d51a8..df2bd86 100644 --- a/orcinus/config.php +++ b/orcinus/config.php @@ -117,6 +117,7 @@ if (!in_array($_DDATA['tbprefix'].'config', $_DDATA['tables'], true)) { `s_weight_css` TEXT NOT NULL, `s_show_orphans` BOOLEAN NOT NULL, `s_show_filetype_html` BOOLEAN NOT NULL, + `s_text_fragments` BOOLEAN NOT NULL, `s_charset` TINYTEXT NOT NULL, `s_result_template` TEXT NOT NULL, `s_limit_query_log` TINYINT UNSIGNED NOT NULL, @@ -200,6 +201,7 @@ if (!count($testConf->fetchAll())) { `s_weight_css`=\'.important dt h1 h2 h3\', `s_show_orphans`=0, `s_show_filetype_html`=0, + `s_text_fragments`=0, `s_charset`=\'UTF-8\', `s_result_template`=\'\', `s_limit_query_log`=14, diff --git a/orcinus/js/template.offline.js b/orcinus/js/template.offline.js index f156b47..24534ae 100644 --- a/orcinus/js/template.offline.js +++ b/orcinus/js/template.offline.js @@ -54,6 +54,7 @@ function os_page(content_mime, url, category, priority, last_modified, title, de this.content = content; this.matchtext = []; + this.fragment = []; this.relevance = 0; this.multi = -1; @@ -354,8 +355,11 @@ if (os_crawldata.length) { if (splitter.length == 1) { // Grab some random content if there were no // matches in the content - let offset = Math.floor(Math.random() * os_sdata.results[x].content.length - {{s_limit_matchtext}}); - } else offset = Math.floor(Math.max(0, caret - (splitter[z].length + {{s_limit_matchtext}}) / 2)); + offset = Math.floor(Math.random() * os_sdata.results[x].content.length - {{s_limit_matchtext}}); + } else { + os_sdata.results[x].fragment.push(splitter[z]); + offset = Math.floor(Math.max(0, caret - (splitter[z].length + {{s_limit_matchtext}}) / 2)); + } let match = os_sdata.results[x].content.substring(offset, offset + {{s_limit_matchtext}}).trim(); // Add appropriate ellipses @@ -484,6 +488,17 @@ if (os_crawldata.length) { } } + // Append text fragment(s) to the URL if applicable + if ({{s_text_fragments}} && resultsPage[x].fragment.length) { + resultsPage[x].fragment = resultsPage[x].fragment.filter(function(v, i, a) { + return a.indexOf(v) === i; + }); + resultsPage[x].fragment = resultsPage[x].fragment.map(function(x) { + return x.replace(',', '%2C').replace('-', '%2D'); + }); + result.url += '#:~:text=' + resultsPage[x].fragment.join('&text='); + } + os_TEMPLATE.searchable.searched.results.result_list.push(result); } diff --git a/orcinus/search.php b/orcinus/search.php index 2d2831b..3087568 100644 --- a/orcinus/search.php +++ b/orcinus/search.php @@ -462,6 +462,7 @@ if ($_RDATA['s_searchable_pages']) { // proper match text for each foreach ($_SDATA['results'] as $key => $row) { $_SDATA['results'][$key]['matchtext'] = array(); + $_SDATA['results'][$key]['fragment'] = array(); // Add the page description to use as a default match text if (trim($row['description'])) { @@ -495,7 +496,10 @@ if ($_RDATA['s_searchable_pages']) { // Grab some random content if there were no // matches in the content $offset = mt_rand(0, mb_strlen($row['content'], 'UTF-8') - $_ODATA['s_limit_matchtext']); - } else $offset = floor(max(0, $split[1] - (mb_strlen($term, 'UTF-8') + $_ODATA['s_limit_matchtext']) / 2)); + } else { + $_SDATA['results'][$key]['fragment'][] = $split[0]; + $offset = floor(max(0, $split[1] - (mb_strlen($term, 'UTF-8') + $_ODATA['s_limit_matchtext']) / 2)); + } $match = trim(mb_substr($row['content'], $offset, $_ODATA['s_limit_matchtext'], 'UTF-8')); // Add appropriate ellipses @@ -735,6 +739,14 @@ if ($_RDATA['s_searchable_pages']) { ), true); } + // Append text fragment(s) to the URL if applicable + if ($_ODATA['s_text_fragments'] && count($result['fragment'])) { + $result['fragment'] = array_map(function($a) { + return str_replace(array(',', '-'), array('%2C', '%2D'), urlencode($a)); + }, array_values(array_unique($result['fragment']))); + $_RESULT->url .= '#:~:text='.implode('&text=', $result['fragment']); + } + $_ORCINUS->searchable->searched->results->result_list[] = $_RESULT; }