mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
docs(docs-infra): always include fragment in search results (#63866)
Always include page fragment/sub-title in the search dialog results. PR Close #63866
This commit is contained in:
parent
5f41f141ee
commit
39cbb97dfc
4 changed files with 94 additions and 78 deletions
|
|
@ -12,35 +12,49 @@
|
|||
@if (searchResults().length) {
|
||||
<ul class="docs-search-results docs-mini-scroll-track">
|
||||
@for (result of searchResults(); track result.id) {
|
||||
<li docsSearchItem [item]="result">
|
||||
<li docsSearchItem [item]="result" class="docs-search-result">
|
||||
<a
|
||||
[routerLink]="'/' + result.url | relativeLink: 'pathname'"
|
||||
[fragment]="result.url | relativeLink: 'hash'"
|
||||
(click)="history.addItem(result)"
|
||||
>
|
||||
<div>
|
||||
<div class="docs-result-icon-and-type">
|
||||
<p class="docs-search-result__label">
|
||||
<!-- Icon -->
|
||||
<span class="docs-search-result-icon" aria-hidden="true">
|
||||
<i role="presentation" class="material-symbols-outlined docs-icon-small">
|
||||
{{ result.type === 'code' ? 'code' : 'description'}}
|
||||
</i>
|
||||
</span>
|
||||
<!-- Results type -->
|
||||
<span class="docs-search-results__type" [innerHtml]="result.labelHtml"></span>
|
||||
</div>
|
||||
|
||||
<!-- Page title -->
|
||||
<span [innerHtml]="result.labelHtml"></span>
|
||||
@if (result.package) {
|
||||
<span
|
||||
[innerHTML]="result.package"
|
||||
class="docs-search-result__label__package"
|
||||
></span>
|
||||
}
|
||||
</p>
|
||||
|
||||
@if (result.subLabelHtml) {
|
||||
<span
|
||||
class="docs-search-results__type docs-search-results__lvl2"
|
||||
[innerHtml]="result.subLabelHtml"
|
||||
>
|
||||
</span>
|
||||
<p class="docs-search-result__sub-label">
|
||||
<span class="docs-search-result-icon" aria-hidden="true">
|
||||
<i role="presentation" class="material-symbols-outlined docs-icon-small">
|
||||
grid_3x3
|
||||
</i>
|
||||
</span>
|
||||
<span [innerHtml]="result.subLabelHtml"></span>
|
||||
</p>
|
||||
}
|
||||
|
||||
@if (result.contentHtml) {
|
||||
<p class="docs-search-result__content" [innerHtml]="result.contentHtml"></p>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Page title -->
|
||||
<span class="docs-result-page-title">{{ result.category }}</span>
|
||||
<p class="docs-search-result__category">
|
||||
{{ result.category }}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,11 +38,21 @@ dialog {
|
|||
margin: 0;
|
||||
border-block-end: 1px solid var(--senary-contrast);
|
||||
|
||||
li {
|
||||
.docs-search-result {
|
||||
border-inline-start: 2px solid var(--senary-contrast);
|
||||
margin-inline-start: 1rem;
|
||||
padding-inline-end: 1rem;
|
||||
padding-block: 0.25rem;
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
|
||||
.docs-search-result-icon {
|
||||
display: inline-block;
|
||||
|
||||
i {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This rule needs ng-deep to be applied to elements that are created via a [innerHTML] binding
|
||||
|
|
@ -61,17 +71,50 @@ dialog {
|
|||
color: var(--secondary-contrast);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.docs-search-result-icon {
|
||||
i {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
&__label,
|
||||
&__sub-label,
|
||||
&__content {
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
&__label,
|
||||
&__sub-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-weight: 600;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&__package {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
&__content,
|
||||
&__category {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__sub-label,
|
||||
&__content {
|
||||
margin-block-start: 0.375rem;
|
||||
margin-inline-start: 2rem;
|
||||
color: var(--quaternary-contrast);
|
||||
}
|
||||
|
||||
&__category {
|
||||
font-weight: 400;
|
||||
color: var(--quaternary-contrast);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: var(--septenary-contrast); // stylelint-disable-line
|
||||
}
|
||||
|
|
@ -80,44 +123,14 @@ dialog {
|
|||
&.active {
|
||||
background-color: var(--octonary-contrast); // stylelint-disable-line
|
||||
border-inline-start: 2px solid var(--primary-contrast);
|
||||
a {
|
||||
span:not(.docs-result-page-title),
|
||||
.docs-search-results__type {
|
||||
color: var(--primary-contrast);
|
||||
i {
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
.docs-search-result__label,
|
||||
.docs-search-result__sub-label,
|
||||
.docs-search-result__content {
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.docs-search-result-icon,
|
||||
.docs-search-results__type,
|
||||
.docs-result-page-title {
|
||||
color: var(--quaternary-contrast);
|
||||
display: inline-block;
|
||||
font-size: 0.875rem;
|
||||
transition: color 0.3s ease;
|
||||
padding: 0.75rem;
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
|
||||
.docs-search-results__lvl2 {
|
||||
display: inline-block;
|
||||
margin-inline-start: 2rem;
|
||||
padding-block-start: 0;
|
||||
}
|
||||
|
||||
.docs-search-results__lvl3 {
|
||||
margin-inline-start: 2rem;
|
||||
padding-block-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-result-page-title {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,14 +140,6 @@ dialog {
|
|||
color: var(--gray-400);
|
||||
}
|
||||
|
||||
.docs-result-icon-and-type {
|
||||
display: flex;
|
||||
|
||||
.docs-search-results__type {
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-search-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ export interface SearchResultItem {
|
|||
type: 'doc' | 'code';
|
||||
labelHtml: string | null;
|
||||
subLabelHtml: string | null;
|
||||
contentHtml: string | null;
|
||||
package: string | null;
|
||||
url: string;
|
||||
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -144,13 +144,8 @@ export class Search {
|
|||
return this.getUniqueSearchResultItems(items).map((hitItem: SearchResult): SearchResultItem => {
|
||||
const content = hitItem._snippetResult.content;
|
||||
const hierarchy = hitItem._snippetResult.hierarchy;
|
||||
const type = hitItem.hierarchy.lvl0 === 'Tutorials' ? 'code' : 'doc';
|
||||
const category = hitItem.hierarchy?.lvl0 ?? null;
|
||||
const hasSubLabel = content || hierarchy?.lvl2 || hierarchy?.lvl3 || hierarchy?.lvl4;
|
||||
const subLabelHtml =
|
||||
category === 'Reference'
|
||||
? extractPackageNameFromUrl(hitItem.url)
|
||||
: this.parseLabelToHtml(hasSubLabel ? this.getBestSnippetForMatch(hitItem) : null);
|
||||
const hasSubLabel = hierarchy?.lvl2 || hierarchy?.lvl3 || hierarchy?.lvl4;
|
||||
|
||||
return {
|
||||
id: hitItem.objectID,
|
||||
|
|
@ -158,18 +153,18 @@ export class Search {
|
|||
url: hitItem.url,
|
||||
|
||||
labelHtml: this.parseLabelToHtml(hitItem._snippetResult.hierarchy?.lvl1?.value ?? ''),
|
||||
subLabelHtml,
|
||||
subLabelHtml: this.parseLabelToHtml(
|
||||
hasSubLabel ? this.getBestSnippetForMatch(hitItem) : null,
|
||||
),
|
||||
contentHtml: content ? this.parseLabelToHtml(content.value) : null,
|
||||
package: category === 'Reference' ? extractPackageNameFromUrl(hitItem.url) : null,
|
||||
|
||||
category: hitItem.hierarchy?.lvl0 ?? null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private getBestSnippetForMatch(result: SearchResult): string {
|
||||
// if there is content, return it
|
||||
if (result._snippetResult.content !== undefined) {
|
||||
return result._snippetResult.content.value;
|
||||
}
|
||||
|
||||
const hierarchy = result._snippetResult.hierarchy;
|
||||
if (hierarchy === undefined) {
|
||||
return '';
|
||||
|
|
@ -242,5 +237,5 @@ function extractPackageNameFromUrl(url: string): string | null {
|
|||
if (extractedSegment == null) {
|
||||
return null;
|
||||
}
|
||||
return `From <code>@angular/${extractedSegment[1]}</code>`;
|
||||
return `<code>@angular/${extractedSegment[1]}</code>`;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue