Skip to content

Commit

Permalink
Registry Refresher: UI changes, search updates & more (#3730)
Browse files Browse the repository at this point in the history
  • Loading branch information
svrnm committed Jan 18, 2024
1 parent 673a229 commit b56dc6b
Show file tree
Hide file tree
Showing 727 changed files with 6,628 additions and 3,187 deletions.
1 change: 1 addition & 0 deletions .cspell.yml
Expand Up @@ -108,6 +108,7 @@ words:
- otep
- otlp
- overridable
- packagist
- Paixão
- parentbased
- Pavol
Expand Down
4 changes: 2 additions & 2 deletions .textlintrc.yml
Expand Up @@ -9,8 +9,8 @@ filters:
allowlist:
allow:
# Don't check registry .yml file fields for language, repo and tags:
- '/^(?:language|repo): .*$/m'
- /^tags:(\s*-.+$)*/m
- '/^\s*(?:language|repo|name|docs): .*$/m'
- /^(?:tags):(\s*-.+$)*/m
# Hugo template syntax:
- /{{.*?}}/
- /{{%.*?%}}/
Expand Down
263 changes: 136 additions & 127 deletions assets/js/registrySearch.js
@@ -1,21 +1,37 @@
let summaryInclude = 60;
let fuseOptions = {
shouldSort: true,
includeMatches: true,
threshold: 0.1,
tokenize: true,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [
{ name: 'title', weight: 0.8 },
{ name: 'description', weight: 0.5 },
{ name: 'tags', weight: 0.3 },
{ name: 'categories', weight: 0.3 },
],
const miniSearchOptions = {
fields: [
'title',
'description',
'_key',
'tags',
'package.name',
'license',
'language',
'registryType',
], // fields to index for full-text search
storeFields: ['title', '_key'], // fields to return with search results
extractField: (document, fieldName) => {
if (Array.isArray(document[fieldName])) {
return document[fieldName].join(' ');
}
return fieldName.split('.').reduce((doc, key) => doc && doc[key], document);
},
searchOptions: {
prefix: true,
boost: {
title: 4,
tags: 3,
description: 2,
},
fuzzy: 0.2,
},
};

const originalDocumentTitle = document.title;

let fetched = false;
const miniSearch = new MiniSearch(miniSearchOptions);

// Get searchQuery for queryParams
let pathName = window.location.pathname;
let searchQuery = '';
Expand All @@ -27,14 +43,9 @@ parseUrlParams();
if (pathName.includes('registry')) {
// Run search or display default body
if (searchQuery) {
document.querySelector('#search-query').value = searchQuery;
document.querySelector('#default-body').style.display = 'none';
executeSearch(searchQuery);
} else {
let defaultBody = document.querySelector('#default-body');
if (defaultBody.style.display === 'none') {
defaultBody.style.display = 'block';
}
showBody();
}

if (selectedLanguage !== 'all' || selectedComponent !== 'all') {
Expand All @@ -52,116 +63,22 @@ if (pathName.includes('registry')) {
}
updateFilters();
}
}

// Runs search through Fuse for fuzzy search
function executeSearch(searchQuery) {
fetch('/ecosystem/registry/index.json')
.then((res) => res.json())
.then((json) => {
let fuse = new Fuse(json, fuseOptions);
let results = fuse.search(searchQuery);

if (results.length > 0) {
populateResults(results);
} else {
document.querySelector('#search-results').innerHTML +=
'<p>No matches found</p>';
}
document.addEventListener('DOMContentLoaded', (event) => {
let searchForm = document.getElementById('searchForm');
searchForm.addEventListener('submit', function (evt) {
evt.preventDefault();
let val = document.getElementById('input-s').value;
setInput('s', val);
parseUrlParams();
executeSearch(searchQuery);
});
}

// Populate the search results and render to the page
function populateResults(results) {
results.forEach((result, key) => {
let contents = result.item.description;
let snippet = '';
let snippetHighlights = [];

if (fuseOptions.tokenize) {
snippetHighlights.push(searchQuery);
} else {
result.matches.forEach((match) => {
if (match.key === 'tags' || match.key === 'categories') {
snippetHighlights.push(match.value);
} else if (match.key === 'description') {
start =
match.indices[0][0] - summaryInclude > 0
? match.indices[0][0] - summaryInclude
: 0;
end =
match.indices[0][1] + summaryInclude < contents.length
? match.indices[0][1] + summaryInclude
: contents.length;
snippet += contents.substring(start, end);
snippetHighlights.push(
match.value.substring(
match.indices[0][0],
match.indices[0][1] - mvalue.indices[0][0] + 1,
),
);
}
});
}

if (snippet.length < 1 && contents.length > 0) {
snippet += contents.substring(0, summaryInclude * 2);
}

// Pull template from hugo template definition
let templateDefinition = document.querySelector(
'#search-result-template',
).innerHTML;

// Replace values from template with search results
let output = render(templateDefinition, {
key: key,
title: result.item.title,
link: result.item.permalink,
tags: result.item.tags,
categories: result.item.categories,
description: result.item.description,
repo: result.item.repo,
registryType: result.item.registryType,
language: result.item.language,
snippet: snippet,
otVersion: result.item.otVersion,
let searchInput = document.getElementById('input-s');
searchInput.addEventListener('keyup', function (evt) {
autoSuggest(evt.target.value);
});
document.querySelector('#search-results').innerHTML += output;
});
}

// Helper function to generate HTML for a search result
function render(templateString, data) {
let conditionalMatches, conditionalPattern, copy;
conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g;
//since loop below depends on re.lastInxdex, we use a copy to capture any manipulations whilst inside the loop
copy = templateString;
while (
(conditionalMatches = conditionalPattern.exec(templateString)) !== null
) {
if (data[conditionalMatches[1]]) {
//valid key, remove conditionals, leave contents.
copy = copy.replace(conditionalMatches[0], conditionalMatches[2]);
} else {
//not valid, remove entire section
copy = copy.replace(conditionalMatches[0], '');
}
}
templateString = copy;

//now any conditionals removed we can do simple substitution
let key, find, re;
for (key in data) {
find = '\\$\\{\\s*' + key + '\\s*\\}';
re = new RegExp(find, 'g');
templateString = templateString.replace(re, data[key]);
}
return templateString;
}

if (pathName.includes('registry')) {
document.addEventListener('DOMContentLoaded', (event) => {
let languageList = document
.getElementById('languageFilter')
.querySelectorAll('.dropdown-item');
Expand Down Expand Up @@ -191,6 +108,98 @@ if (pathName.includes('registry')) {
});
}

function showBody() {
document.title = originalDocumentTitle;
document.querySelector('#search-results').innerHTML = '';
let defaultBody = document.querySelector('#default-body');
if (defaultBody.style.display === 'none') {
defaultBody.style.display = 'block';
}
}

// Runs search through Fuse for fuzzy search
function executeSearch(searchQuery) {
if (searchQuery === '') {
showBody();
return;
}

document.title = searchQuery + ' at ' + originalDocumentTitle;
document.querySelector('#input-s').value = searchQuery;
document.querySelector('#default-body').style.display = 'none';
document.querySelector('#search-results').innerHTML = '';
document.getElementById('search-loading').style.display = 'block';

const run = function (searchQuery) {
// The 0-timeout is here if search is blocking, such that the "search loading" is rendered properly
setTimeout(() => {
let results = miniSearch.search(searchQuery);
document.getElementById('search-loading').style.display = 'none';

if (results.length > 0) {
populateResults(results);
} else {
document.querySelector('#search-results').innerHTML +=
'<p>No matches found</p>';
}
}, 0);
};

if (fetched) {
run(searchQuery);
} else {
fetch('/ecosystem/registry/index.json')
.then((res) => res.json())
.then((json) => {
fetched = true;
miniSearch.addAll(json);
run(searchQuery);
});
}
}

function autoSuggest(value) {
if (value === '') {
return;
}

const run = function (value) {
const suggestions = miniSearch.autoSuggest(value, {
// we only use title, otherwise we get strange suggestions, especially with description
fields: ['title'],
});
const list = document.getElementById('search-suggestions');
list.innerHTML = suggestions
.map(({ suggestion }) => `<option>${suggestion}</option>`)
.join('');
};

if (fetched) {
run(value);
} else {
fetch('/ecosystem/registry/index.json')
.then((res) => res.json())
.then((json) => {
fetched = true;
miniSearch.addAll(json);
run(value);
});
}
}

// Populate the search results and render to the page
function populateResults(results) {
document.querySelector('#search-results').innerHTML += results.reduce(
(acc, result) => {
return (
acc +
document.querySelector(`[data-registry-id="${result._key}"]`).outerHTML
);
},
'',
);
}

function setInput(key, value) {
document.getElementById(`input-${key}`).value = value;
var queryParams = new URLSearchParams(window.location.search);
Expand Down
39 changes: 39 additions & 0 deletions assets/scss/_registry.scss
Expand Up @@ -6,6 +6,13 @@
}
}

@each $component, $color in $otel-registry-license-colors {
&.badge-#{$component} {
color: white;
background-color: $color;
}
}

&.badge-elixir {
color: map-get($otel-component-colors, erlang);
background-color: inherit;
Expand All @@ -28,3 +35,35 @@
color: color-contrast($default-otel-badge-bg);
background-color: $default-otel-badge-bg;
}

.registry-entry {
@extend .shadow;
}

// fix me: the registry seems not to load the main.min.css with the extended
// styles, so we need to define the styles here again.
.highlight {
margin: 1rem 0;
padding: 0;
position: relative;
max-width: 95%;
border: var(--bs-card-border-width) solid var(--bs-card-border-color);
border-radius: var(--bs-card-border-radius);
& pre {
padding: 1rem;
margin: 0;
display: block;
text-align: right;
overflow-y: auto;
& button.td-click-to-copy {
position: absolute;
color: #ced4da;
border-radius: 3px;
border-width: 0;
background-color: inherit;
box-shadow: 1px 1px #ced4da;
right: 4px;
top: 2px;
}
}
}
7 changes: 7 additions & 0 deletions assets/scss/_variables_project.scss
Expand Up @@ -33,6 +33,13 @@ $otel-component-colors: (
'utilities': #2cd3b4,
);

$otel-registry-license-colors: (
'apache-20': #e83e8c,
'bsd-2-clause': #8ce83e,
'mit': #3e8ce8,
'artistic-10-perl': #e8c83e,
);

$primary: map-get($otel-colors, 'blue');
$secondary: map-get($otel-colors, 'orange');
$td-enable-google-fonts: false;
2 changes: 1 addition & 1 deletion content/en/docs/languages/php/_index.md
Expand Up @@ -4,7 +4,7 @@ description: >-
<img width="35" class="img-initial" src="/img/logos/32x32/PHP.svg" alt="PHP">
A language-specific implementation of OpenTelemetry in PHP.
weight: 21
cSpell:ignore: mbstring opcache packagist
cSpell:ignore: mbstring opcache
---

{{% docs/languages/index-intro php /%}}
Expand Down
2 changes: 1 addition & 1 deletion content/en/docs/languages/php/automatic.md
Expand Up @@ -3,7 +3,7 @@ title: Automatic Instrumentation
linkTitle: Automatic
weight: 30
# prettier-ignore
cSpell:ignore: centos configurator democlass epel myapp packagist pecl phar remi unindented userland
cSpell:ignore: centos configurator democlass epel myapp pecl phar remi unindented userland
---

Automatic instrumentation with PHP requires at least PHP 8.0, and the
Expand Down

0 comments on commit b56dc6b

Please sign in to comment.