Add text fragments flag and functionality

This commit is contained in:
Brian Huisman 2023-09-14 13:18:33 -04:00
parent da52e0f7bf
commit 873a18fbc9
4 changed files with 66 additions and 5 deletions

View file

@ -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'][] = <<<ORCINUS
Note: <code>rel="noopener"</code> has been added to the links in your result template.
<a href="https://developer.mozilla.org/en-US/docs/Web/Text_fragments#:~:text=noopener" rel="noopener" target="_blank">More info...</a>
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'])) { ?>
<div class="col-10 col-sm-8 col-md-7">
<div class="alert alert-danger alert-dismissible fade show mx-auto" role="alert"><?php
echo htmlspecialchars($error); ?>
echo $error; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</div><?php
@ -1368,7 +1392,7 @@ if (!$_SESSION['admin_username']) {
while ($message = array_shift($_SESSION['message'])) { ?>
<div class="col-10 col-sm-8 col-md-7">
<div class="alert alert-info alert-dismissible fade show mx-auto" role="alert"><?php
echo htmlspecialchars($message); ?>
echo $message; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</div><?php
@ -2537,6 +2561,14 @@ if (!$_SESSION['admin_username']) {
if ($_ODATA['s_show_filetype_html']) echo ' checked="checked"'; ?>>
<label for="os_s_show_filetype_html" class="form-check-label">Show [HTML] filetype in search results</label>
</li>
<li class="form-check mb-1">
<input type="checkbox" name="os_s_text_fragments" id="os_s_text_fragments" value="1" class="form-check-input"
data-bs-toggle="tooltip" data-bs-placement="top" title="Use special links that try to highlight the first match of each term on the target page."<?php
if ($_ODATA['s_text_fragments']) echo ' checked="checked"'; ?>>
<label for="os_s_text_fragments" class="form-check-label">
Use <a href="https://developer.mozilla.org/en-US/docs/Web/Text_fragments#:~:text=Text%20fragment" rel="noopener" target="_blank">text fragments</a> in result links
</label>
</li>
</ul>
</div>
</div>

View file

@ -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,

View file

@ -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);
}

View file

@ -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;
}