Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

index videos and add external data to search #1266

Merged
merged 11 commits into from
Nov 13, 2023
16 changes: 16 additions & 0 deletions packages/lit-dev-content/.eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,22 @@ ${content}
return value;
});

eleventyConfig.addFilter('videosToAlgoliaRecords', function (videos) {
return videos.map((video) => {
return {
relativeUrl: video.url,
title: video.title,
heading: '',
text: video.summary,
docType: {
type: 'Video',
tag: 'video',
},
isExternal: true,
};
});
});

const sortDocs = (a, b) => {
if (a.fileSlug == 'docs') {
return -1;
Expand Down
44 changes: 44 additions & 0 deletions packages/lit-dev-content/site/_data/externalSearchData.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,49 @@
"tag": "other"
},
"isExternal": true
},
{
"relativeUrl": "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals",
"title": "HTMLElement: attachInternals() method",
"heading": "",
"text": "The HTMLElement.attachInternals() method returns an ElementInternals object. This method allows a custom element to participate in HTML forms. The ElementInternals interface provides utilities for working with these elements in the same way you would work with any standard HTML form element, and also exposes the Accessibility Object Model to the element.",
"docType": {
"type": "MDN",
"tag": "other"
},
"isExternal": true
},
{
"relativeUrl": "https://webkit.org/blog/13711/elementinternals-and-form-associated-custom-elements/",
"title": "ElementInternals and Form-Associated Custom Elements",
"heading": "",
"text": "In Safari Technology Preview 162 we enabled the support for ElementInternals and the form-associated custom elements by default. Custom elements is a feature which lets web developers create reusable components by defining their own HTML elements without relying on a JavaScript framework. ElementInternals is a new addition to custom elements API, which allows developers to manage a custom element’s internal states such as default ARIA role or ARIA label as well as having custom elements participate in form submissions and validations.",
"docType": {
"type": "WebKit",
"tag": "other"
},
"isExternal": true
},
{
"relativeUrl": "https://web.dev/articles/more-capable-form-controls",
"title": "More capable form controls",
"heading": "",
"text": "With a new event, and custom elements APIs, participating in forms just got a lot easier. Many developers build custom form controls, either to provide controls that aren't built in to the browser, or to customize the look and feel beyond what's possible with the built-in form controls. However, it can be difficult to replicate the features of built-in HTML form controls. Consider some of the features an <input> element gets automatically when you add it to a form: The input is automatically added to the form's list of controls. The input's value is automatically submitted with the form. The input participates in form validation. You can style the input using the :valid and :invalid pseudoclasses. The input is notified when the form is reset, when the form is reloaded, or when the browser tries to autofill form entries. Custom form controls typically have few of these features. Developers can work around some of the limitations in JavaScript, like adding a hidden <input> to a form to participate in form submission. But other features just can't be replicated in JavaScript alone. Two new web features make it easier to build custom form controls, and remove the limitations of current custom controls: The formdata event lets an arbitrary JavaScript object participate in form submission, so you can add form data without using a hidden <input>. The Form-associated custom elements API lets custom elements act more like built-in form controls. These two features can be used to create new kinds of controls that work better.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this maybe a bit long? Will Algolia return this whole block of text for the search -option text snippet?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it only returns the relevant snippet like in the first image

"docType": {
"type": "Web.dev",
"tag": "other"
},
"isExternal": true
},
{
"relativeUrl": "https://stackblitz.com/edit/stackblitz-starters-bdtxdy?file=stories%2FButton.js,components%2Fmy-button.js",
"title": "Lit + Storybook Example",
"heading": "",
"text": "Using npx storybook@latest init and following the prompts for web components, you can generate a Storybook project for your Lit Elements like this project!",
"docType": {
"type": "StackBlitz",
"tag": "other"
},
"isExternal": true
}
]
5 changes: 5 additions & 0 deletions packages/lit-dev-content/site/external-search-data/data.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
permalink: external-search-data/data.json
---

{% if not env.DEV %}{{ externalSearchData | dump | safe }}{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
permalink: external-search-data/videos.json
---

{% if not env.DEV %}
{{ videos | videosToAlgoliaRecords | dump | safe }}
{% endif %}
18 changes: 15 additions & 3 deletions packages/lit-dev-content/src/components/litdev-search-option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {LitElement, html, css, PropertyValues} from 'lit';
import {property, customElement} from 'lit/decorators.js';
import {hashtagIcon} from '../icons/hashtag-icon.js';
import {paperDocumentIcon} from '../icons/paper-document-icon.js';
import {openInNewIcon} from '../icons/open-in-new-icon.js';
import {renderAlgoliaSnippet} from '../util/render-algolia-suggestions.js';

/**
Expand All @@ -33,6 +34,9 @@ export class LitdevSearchOption extends LitElement {
@property({type: Boolean, attribute: true})
checked = false;

@property({type: Boolean})
isExternal = false;

static styles = css`
:host {
display: block;
Expand Down Expand Up @@ -107,21 +111,29 @@ export class LitdevSearchOption extends LitElement {
`;

render() {
const showText = this.isSubsection || (this.isExternal && this.text);
return html`
<div class="suggestion">
<div class="icon-wrapper" aria-hidden="true">
${this.isSubsection ? hashtagIcon : paperDocumentIcon}
</div>
<div class="title-and-text ${this.isSubsection ? 'has-text' : ''}">
${this.isSubsection
<div class="title-and-text ${showText ? 'has-text' : ''}">
${showText
? html`<span class="title">
${renderAlgoliaSnippet(this.heading)}
${renderAlgoliaSnippet(this.heading || this.title)}
</span>
<span class="text"> ${renderAlgoliaSnippet(this.text)} </span>`
: html`<span class="title">
${renderAlgoliaSnippet(this.title)}
</span>`}
</div>
${this.isExternal
? html`
<div class="icon-wrapper end" aria-hidden="true">
${openInNewIcon}
</div>
`
: ''}
</div>
`;
}
Expand Down
31 changes: 23 additions & 8 deletions packages/lit-dev-content/src/components/litdev-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import './lazy-svg.js';
/**
* Generic that denotes the type of document.
*/
interface DocType<T extends string, U extends string> {
type: T;
interface DocType<U extends string> {
type: string;
tag: U;
}

Expand All @@ -29,11 +29,13 @@ interface DocType<T extends string, U extends string> {
* frontend and used to re-rank results on the frontend.
*/
type DocTypes =
| DocType<'Article', 'article'>
| DocType<'Tutorial', 'tutorial'>
| DocType<'Docs', 'docs'>
| DocType<'API', 'api'>
| DocType<'Other', 'other'>;
| DocType<'article'>
| DocType<'tutorial'>
| DocType<'docs'>
| DocType<'api'>
| DocType<'video'>
| DocType<'other'>
| DocType<'other'>;
e111077 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Representation of each record indexed by our PageChunker which is published
Expand All @@ -49,6 +51,7 @@ interface UserFacingPageData {
text: string;
parentID?: string;
docType: DocTypes;
isExternal?: boolean;
}

/**
Expand Down Expand Up @@ -269,7 +272,13 @@ export class LitDevSearch extends LitElement {
${repeat(
suggestionGroup.suggestions,
({objectID}) => objectID,
({relativeUrl, _highlightResult, _snippetResult, parentID}) => {
({
relativeUrl,
_highlightResult,
_snippetResult,
parentID,
isExternal,
}) => {
const title = _highlightResult.title.value;
const heading = _highlightResult.heading.value;
const text = _snippetResult.text.value;
Expand All @@ -284,6 +293,7 @@ export class LitDevSearch extends LitElement {
.heading="${heading}"
.text="${text}"
.isSubsection="${!!parentID}"
.isExternal="${!!isExternal}"
role="option"
@pointerenter=${this._onSuggestionHover(suggestionIndex)}
@click="${() => this._navigate(relativeUrl)}"
Expand Down Expand Up @@ -583,6 +593,11 @@ export class LitDevSearch extends LitElement {
background-color: #324fff;
}

.group .tag.video {
color: white;
background-color: #eb0000;
}

.group .tag.tutorial {
color: black;
background-color: #40dcff;
Expand Down
19 changes: 19 additions & 0 deletions packages/lit-dev-content/src/icons/open-in-new-icon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/

import {html} from 'lit';

// Source: https://fonts.google.com/icons?selected=Material+Symbols+Outlined:open_in_new:FILL@0;wght@400;GRAD@0;opsz@24&icon.query=open_in_new
export const openInNewIcon = html` <svg
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="currentcolor"
>
<path
d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h560v-280h80v280q0 33-23.5 56.5T760-120H200Zm188-212-56-56 372-372H560v-80h280v280h-80v-144L388-332Z"
/>
</svg>`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
e111077 marked this conversation as resolved.
Show resolved Hide resolved

import * as fs from 'fs/promises';
import * as path from 'path';
import type {UserFacingPageData} from '../plugin';

export async function indexExternalData(
outputDir: '_dev' | '_site',
idOffset = 0
) {
if (outputDir === '_dev') {
return [];
}

// Path of the external data index.
const EXTERNAL_DATA_INDEX_PATH = path.resolve(
__dirname,
`../../../../lit-dev-content/${outputDir}/external-search-data/data.json`
);

const fileContents = await fs.readFile(EXTERNAL_DATA_INDEX_PATH, 'utf-8');
const data = JSON.parse(fileContents) as UserFacingPageData[];
data.forEach((searchRecord) => {
searchRecord.objectID = `${++idOffset}`;
searchRecord.isExternal = true;
});

return data;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export const indexTutorials = async (
outputDir: string,
idOffset = 0
): Promise<UserFacingPageData[]> => {
if (outputDir === '_dev') {
return [];
}

const TUTORIAL_PATH = path.resolve(
__dirname,
`../../../../lit-dev-content/${outputDir}/tutorials`
Expand Down
29 changes: 29 additions & 0 deletions packages/lit-dev-tools-cjs/src/search/indexers/index-videos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
e111077 marked this conversation as resolved.
Show resolved Hide resolved

import * as fs from 'fs/promises';
import * as path from 'path';
import type {UserFacingPageData} from '../plugin';

export async function indexVideos(outputDir: '_dev' | '_site', idOffset = 0) {
if (outputDir === '_dev') {
return [];
}

// Path of the video index.
const VIDEO_INDEX_PATH = path.resolve(
__dirname,
`../../../../lit-dev-content/${outputDir}/external-search-data/videos.json`
);

const fileContents = await fs.readFile(VIDEO_INDEX_PATH, 'utf-8');
const videos = JSON.parse(fileContents) as UserFacingPageData[];
videos.forEach((video) => {
video.objectID = `${++idOffset}`;
});

return videos;
}
2 changes: 2 additions & 0 deletions packages/lit-dev-tools-cjs/src/search/indexers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export {indexDocs} from './index-docs.js';
export {indexArticles} from './index-articles.js';
export {indexApi} from './index-api.js';
export {indexTutorials} from './index-tutorials.js';
export {indexVideos} from './index-videos.js';
export {indexExternalData} from './index-external-data.js';
5 changes: 1 addition & 4 deletions packages/lit-dev-tools-cjs/src/search/indexers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,7 @@ export const walkDir = async (
*/
export const docIndexer = async (
relativeLinksToHTMLFile: UrlToFile,
docType:
| DocType<'Docs', 'docs'>
| DocType<'API', 'api'>
| DocType<'Article', 'article'>,
docType: DocType<'docs'> | DocType<'api'> | DocType<'article'>,
idOffset: number
) => {
let id = idOffset;
Expand Down
Loading
Loading