Extensions: Add an asyncMap() directive to replace dom-repeat
Add a new AsyncMapDirective class in chrome://extensions, along with corresponding tests. The new directive internally uses map() to display a list of items, and supports |initialCount| and |filter| parameters. These parameters are used by some dom-repeats in the extensions list currently; these dom-repeats will be migrated to use the new directive in a followup. Also adding a test, and adding the relevant code to the lit bundle. lit.rollup.js minified size increases 1.9kB with this change: Before: 17557 bytes After: 19446 bytes Bug: 40943652 Change-Id: I0644fe90da1b584e43ce64eb2bbdebda922fbc2d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5941684 Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Commit-Queue: Rebekah Potter <rbpotter@chromium.org> Reviewed-by: Demetrios Papadopoulos <dpapad@chromium.org> Cr-Commit-Position: refs/heads/main@{#1372729}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
3c949d0885
commit
184b3f7556
8
DEPS
8
DEPS
@@ -763,10 +763,10 @@ deps = {
|
|||||||
'condition': 'non_git_source',
|
'condition': 'non_git_source',
|
||||||
'objects': [
|
'objects': [
|
||||||
{
|
{
|
||||||
'object_name': 'a998f33a6d26e2a5bb38180bca2c03eacaf0d1a6',
|
'object_name': '8eb0a40003464becccc4da796843e35116d0aa2e',
|
||||||
'sha256sum': '96f51f598c2e039ef55c539e54cf9c61366e6fba400063da89da1f65ef24d8f4',
|
'sha256sum': 'cb5af9a19b3ec0a01717022bbaa3bd0974f21e18db5397c097af4a54c198080e',
|
||||||
'size_bytes': 8882240,
|
'size_bytes': 8877615,
|
||||||
'generation': 1729207266099094,
|
'generation': 1729559018744319,
|
||||||
'output_file': 'node_modules.tar.gz',
|
'output_file': 'node_modules.tar.gz',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@@ -52,6 +52,7 @@ build_webui("build") {
|
|||||||
]
|
]
|
||||||
|
|
||||||
non_web_component_files = [
|
non_web_component_files = [
|
||||||
|
"async_map_directive.ts",
|
||||||
"drag_and_drop_handler.ts",
|
"drag_and_drop_handler.ts",
|
||||||
"extensions.ts",
|
"extensions.ts",
|
||||||
"item_mixin.ts",
|
"item_mixin.ts",
|
||||||
|
138
chrome/browser/resources/extensions/async_map_directive.ts
Normal file
138
chrome/browser/resources/extensions/async_map_directive.ts
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
// Copyright 2024 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import {assert} from 'chrome://resources/js/assert.js';
|
||||||
|
import {AsyncDirective, directive, html, noChange, PartType} from 'chrome://resources/lit/v3_0/lit.rollup.js';
|
||||||
|
import type {ChildPart, DirectiveParameters, PartInfo, TemplateResult} from 'chrome://resources/lit/v3_0/lit.rollup.js';
|
||||||
|
|
||||||
|
// Directive to render some items in an array asynchronously. Initially
|
||||||
|
// renders `initialCount` items, and renders remaining items asynchronously
|
||||||
|
// in chunking mode, where each chunk is rendered on a subsequent animation
|
||||||
|
// frame. Chunk size is initialized to `initialCount` and increases by
|
||||||
|
// `initialCount` when frames render more quickly than the target, and halves if
|
||||||
|
// frames render more slowly than the target (20fps).
|
||||||
|
// Also supports passing a filter function, to only render items in the array
|
||||||
|
// that match the filter (i.e. items for which filter(item) === true).
|
||||||
|
// Dispatches a 'rendered-items-changed' event, with a `detail` property set
|
||||||
|
// to the total number of rendered items, each time the rendered items are
|
||||||
|
// updated.
|
||||||
|
class AsyncMapDirective<T> extends AsyncDirective {
|
||||||
|
template: (item: T) => TemplateResult = _item => html``;
|
||||||
|
initialCount: number = -1;
|
||||||
|
items: T[] = [];
|
||||||
|
filter: ((item: T) => boolean)|null = null;
|
||||||
|
|
||||||
|
private chunkSize_: number = -1;
|
||||||
|
private filteredItems_: T[] = [];
|
||||||
|
private renderedItems_: T[] = [];
|
||||||
|
private renderStartTime_: number = 0;
|
||||||
|
private targetElapsedTime_: number = 50; // 20fps
|
||||||
|
private eventTarget_: EventTarget|null = null;
|
||||||
|
private requestId_: number|null = null;
|
||||||
|
|
||||||
|
constructor(partInfo: PartInfo) {
|
||||||
|
super(partInfo);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
partInfo.type === PartType.CHILD,
|
||||||
|
'asyncMap() can only be used in text expressions');
|
||||||
|
}
|
||||||
|
|
||||||
|
override update(part: ChildPart, [
|
||||||
|
items,
|
||||||
|
template,
|
||||||
|
initialCount,
|
||||||
|
filter,
|
||||||
|
]: DirectiveParameters<this>) {
|
||||||
|
this.eventTarget_ = part.parentNode instanceof ShadowRoot ?
|
||||||
|
part.parentNode.host :
|
||||||
|
part.parentNode;
|
||||||
|
return this.render(items, template, initialCount, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(
|
||||||
|
items: T[], template: ((item: T) => TemplateResult), initialCount: number,
|
||||||
|
filter: (((item: T) => boolean)|null) = null) {
|
||||||
|
if (items === this.items && filter === this.filter) {
|
||||||
|
return noChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isConnected) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.template = template;
|
||||||
|
this.items = items;
|
||||||
|
this.filter = filter;
|
||||||
|
this.filteredItems_ = filter ? items.filter(i => filter(i)) : items;
|
||||||
|
assert(initialCount > 0);
|
||||||
|
this.initialCount = initialCount;
|
||||||
|
if (this.chunkSize_ === -1) {
|
||||||
|
this.chunkSize_ = this.initialCount;
|
||||||
|
}
|
||||||
|
this.renderedItems_ = this.filteredItems_.slice(0, this.initialCount);
|
||||||
|
const initialRender = this.renderItems_();
|
||||||
|
this.renderInChunks_();
|
||||||
|
return initialRender;
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderItems_(): TemplateResult {
|
||||||
|
// Notify interested parties. Async so that rendering the new items is
|
||||||
|
// done before the event is fired.
|
||||||
|
const numItems = this.renderedItems_.length;
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.eventTarget_) {
|
||||||
|
this.eventTarget_.dispatchEvent(new CustomEvent(
|
||||||
|
'rendered-items-changed',
|
||||||
|
{bubbles: true, composed: true, detail: numItems}));
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
this.renderStartTime_ = performance.now();
|
||||||
|
return html`${this.renderedItems_.map(item => this.template(item))}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async renderInChunks_() {
|
||||||
|
let length = this.renderedItems_.length;
|
||||||
|
const arrayRef = this.filteredItems_;
|
||||||
|
while (length < arrayRef.length) {
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
this.requestId_ = requestAnimationFrame(() => {
|
||||||
|
if (this.requestId_) {
|
||||||
|
cancelAnimationFrame(this.requestId_);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.isConnected || this.filteredItems_ !== arrayRef) {
|
||||||
|
return; // value updated, no longer our loop
|
||||||
|
}
|
||||||
|
|
||||||
|
const elapsed = performance.now() - this.renderStartTime_;
|
||||||
|
|
||||||
|
// Additive increase, multiplicative decrease
|
||||||
|
if (elapsed < this.targetElapsedTime_) {
|
||||||
|
this.chunkSize_ += this.initialCount;
|
||||||
|
} else {
|
||||||
|
this.chunkSize_ = Math.max(1, Math.floor(this.chunkSize_ / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
const newLength = Math.min(length + this.chunkSize_, arrayRef.length);
|
||||||
|
this.renderedItems_.push(...this.filteredItems_.slice(length, newLength));
|
||||||
|
length = newLength;
|
||||||
|
this.setValue(this.renderItems_());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AsyncMapDirectiveFn {
|
||||||
|
<T>(
|
||||||
|
items: T[],
|
||||||
|
template: (item: T) => TemplateResult,
|
||||||
|
initialCount: number,
|
||||||
|
filter?: ((item: T) => boolean)|null,
|
||||||
|
): unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const asyncMap = directive(AsyncMapDirective) as AsyncMapDirectiveFn;
|
@@ -14,6 +14,7 @@ export {ActivityLogHistoryElement, ActivityLogPageState} from './activity_log/ac
|
|||||||
export {ActivityGroup, ActivityLogHistoryItemElement} from './activity_log/activity_log_history_item.js';
|
export {ActivityGroup, ActivityLogHistoryItemElement} from './activity_log/activity_log_history_item.js';
|
||||||
export {ActivityLogStreamElement} from './activity_log/activity_log_stream.js';
|
export {ActivityLogStreamElement} from './activity_log/activity_log_stream.js';
|
||||||
export {ActivityLogStreamItemElement, ARG_URL_PLACEHOLDER, StreamItem} from './activity_log/activity_log_stream_item.js';
|
export {ActivityLogStreamItemElement, ARG_URL_PLACEHOLDER, StreamItem} from './activity_log/activity_log_stream_item.js';
|
||||||
|
export {asyncMap} from './async_map_directive.js';
|
||||||
export {CodeSectionElement} from './code_section.js';
|
export {CodeSectionElement} from './code_section.js';
|
||||||
export {ExtensionsDetailViewElement} from './detail_view.js';
|
export {ExtensionsDetailViewElement} from './detail_view.js';
|
||||||
export {ErrorPageDelegate, ExtensionsErrorPageElement} from './error_page.js';
|
export {ErrorPageDelegate, ExtensionsErrorPageElement} from './error_page.js';
|
||||||
|
@@ -37,6 +37,7 @@ build_webui_tests("build") {
|
|||||||
"navigation_helper_test.ts",
|
"navigation_helper_test.ts",
|
||||||
"options_dialog_test.ts",
|
"options_dialog_test.ts",
|
||||||
"pack_dialog_test.ts",
|
"pack_dialog_test.ts",
|
||||||
|
"async_map_directive_test.ts",
|
||||||
"review_panel_test.ts",
|
"review_panel_test.ts",
|
||||||
"runtime_host_permissions_test.ts",
|
"runtime_host_permissions_test.ts",
|
||||||
"runtime_hosts_dialog_test.ts",
|
"runtime_hosts_dialog_test.ts",
|
||||||
|
175
chrome/test/data/webui/extensions/async_map_directive_test.ts
Normal file
175
chrome/test/data/webui/extensions/async_map_directive_test.ts
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
// Copyright 2024 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
/** @fileoverview Suite of tests for the RepeatDirective class. */
|
||||||
|
import 'chrome://extensions/extensions.js';
|
||||||
|
|
||||||
|
import {PromiseResolver} from '//resources/js/promise_resolver.js';
|
||||||
|
import {asyncMap} from 'chrome://extensions/extensions.js';
|
||||||
|
import {CrLitElement, html} from 'chrome://resources/lit/v3_0/lit.rollup.js';
|
||||||
|
import {assertEquals, assertGT, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
|
||||||
|
|
||||||
|
suite('AsyncMapDirectiveTest', function() {
|
||||||
|
let initialCount: number = 3;
|
||||||
|
let testElement: TestElement;
|
||||||
|
class TestElement extends CrLitElement {
|
||||||
|
static get is() {
|
||||||
|
return 'test-element';
|
||||||
|
}
|
||||||
|
|
||||||
|
override render() {
|
||||||
|
return html`
|
||||||
|
<div @rendered-items-changed="${this.onRenderedItemsChanged_}">
|
||||||
|
${
|
||||||
|
asyncMap(
|
||||||
|
this.items, item => html`<div class="item">${item}</div>`,
|
||||||
|
initialCount, this.filter)}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static override get properties() {
|
||||||
|
return {
|
||||||
|
items: {type: Array},
|
||||||
|
filter: {type: Object},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
items: string[] = [
|
||||||
|
'One',
|
||||||
|
'Two',
|
||||||
|
'Three',
|
||||||
|
'Four',
|
||||||
|
'Five',
|
||||||
|
'Six',
|
||||||
|
'Seven',
|
||||||
|
'Eight',
|
||||||
|
'Nine',
|
||||||
|
'Ten',
|
||||||
|
'Eleven',
|
||||||
|
'Twelve',
|
||||||
|
];
|
||||||
|
filter: ((item: string) => boolean)|null = null;
|
||||||
|
private itemsRendered_: number[] = [];
|
||||||
|
private allItemsRendered_: PromiseResolver<number[]> =
|
||||||
|
new PromiseResolver<number[]>();
|
||||||
|
|
||||||
|
private onRenderedItemsChanged_(e: CustomEvent<number>) {
|
||||||
|
this.itemsRendered_.push(e.detail);
|
||||||
|
const matchingItems = this.filter === null ?
|
||||||
|
this.items :
|
||||||
|
this.items.filter(item => this.filter!(item));
|
||||||
|
if (e.detail === matchingItems.length) {
|
||||||
|
this.allItemsRendered_.resolve(this.itemsRendered_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allItemsRendered(): Promise<number[]> {
|
||||||
|
return this.allItemsRendered_.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.allItemsRendered_ = new PromiseResolver<number[]>();
|
||||||
|
this.itemsRendered_ = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
splice(start: number, deleteCount: number, insertions: string[] = []) {
|
||||||
|
this.items.splice(start, deleteCount, ...insertions);
|
||||||
|
this.requestUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define(TestElement.is, TestElement);
|
||||||
|
|
||||||
|
setup(function() {
|
||||||
|
document.body.innerHTML = window.trustedTypes!.emptyHTML;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Basic', async () => {
|
||||||
|
testElement = document.createElement('test-element') as TestElement;
|
||||||
|
document.body.appendChild(testElement);
|
||||||
|
|
||||||
|
let itemsRendered = await testElement.allItemsRendered();
|
||||||
|
// Additive increase means that we render 3 items, then at most 6 on the
|
||||||
|
// second cycle. So we should have at least 3 calls.
|
||||||
|
assertGT(itemsRendered.length, 2);
|
||||||
|
assertEquals(3, itemsRendered[0]);
|
||||||
|
assertEquals(12, itemsRendered[itemsRendered.length - 1]);
|
||||||
|
|
||||||
|
// Make sure the items are actually in the DOM.
|
||||||
|
assertEquals(12, testElement.shadowRoot!.querySelectorAll('.item').length);
|
||||||
|
|
||||||
|
// Test applying a filter.
|
||||||
|
testElement.reset();
|
||||||
|
testElement.filter = (item: string) => item.startsWith('T');
|
||||||
|
itemsRendered = await testElement.allItemsRendered();
|
||||||
|
assertEquals(4, itemsRendered[itemsRendered.length - 1]);
|
||||||
|
let items = testElement.shadowRoot!.querySelectorAll('.item');
|
||||||
|
assertEquals(4, items.length);
|
||||||
|
assertEquals('Two', items[0]!.textContent!);
|
||||||
|
assertEquals('Three', items[1]!.textContent!);
|
||||||
|
assertEquals('Ten', items[2]!.textContent!);
|
||||||
|
assertEquals('Twelve', items[3]!.textContent!);
|
||||||
|
|
||||||
|
// Filter with no matches
|
||||||
|
testElement.reset();
|
||||||
|
testElement.filter = (item: string) => item.startsWith('Z');
|
||||||
|
itemsRendered = await testElement.allItemsRendered();
|
||||||
|
assertEquals(1, itemsRendered.length);
|
||||||
|
assertEquals(0, itemsRendered[0]);
|
||||||
|
assertEquals(0, testElement.shadowRoot!.querySelectorAll('.item').length);
|
||||||
|
|
||||||
|
// Clear the filter.
|
||||||
|
testElement.reset();
|
||||||
|
testElement.filter = null;
|
||||||
|
itemsRendered = await testElement.allItemsRendered();
|
||||||
|
assertEquals(12, itemsRendered[itemsRendered.length - 1]);
|
||||||
|
items = testElement.shadowRoot!.querySelectorAll('.item');
|
||||||
|
assertEquals(12, items.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Different initial count', async () => {
|
||||||
|
initialCount = 6;
|
||||||
|
testElement = document.createElement('test-element') as TestElement;
|
||||||
|
document.body.appendChild(testElement);
|
||||||
|
|
||||||
|
const itemsRendered = await testElement.allItemsRendered();
|
||||||
|
assertNotEquals(0, itemsRendered.length);
|
||||||
|
assertEquals(6, itemsRendered[0]);
|
||||||
|
assertEquals(12, itemsRendered[itemsRendered.length - 1]);
|
||||||
|
|
||||||
|
// Make sure the items are actually in the DOM.
|
||||||
|
assertEquals(12, testElement.shadowRoot!.querySelectorAll('.item').length);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Modify list', async () => {
|
||||||
|
// Verifies the list updates correctly when the test element updates the
|
||||||
|
// list.
|
||||||
|
testElement = document.createElement('test-element') as TestElement;
|
||||||
|
document.body.appendChild(testElement);
|
||||||
|
|
||||||
|
let itemsRendered = await testElement.allItemsRendered();
|
||||||
|
assertEquals(12, itemsRendered[itemsRendered.length - 1]);
|
||||||
|
assertEquals(12, testElement.shadowRoot!.querySelectorAll('.item').length);
|
||||||
|
|
||||||
|
// Set a new array.
|
||||||
|
testElement.reset();
|
||||||
|
testElement.items = ['Hello', 'World', 'Goodbye'];
|
||||||
|
itemsRendered = await testElement.allItemsRendered();
|
||||||
|
assertEquals(3, itemsRendered[itemsRendered.length - 1]);
|
||||||
|
const renderedItems = testElement.shadowRoot!.querySelectorAll('.item');
|
||||||
|
assertEquals(3, renderedItems.length);
|
||||||
|
assertEquals('Hello', renderedItems[0]!.textContent);
|
||||||
|
assertEquals('World', renderedItems[1]!.textContent);
|
||||||
|
assertEquals('Goodbye', renderedItems[2]!.textContent);
|
||||||
|
|
||||||
|
// Correctly render no items.
|
||||||
|
testElement.reset();
|
||||||
|
testElement.items = [];
|
||||||
|
itemsRendered = await testElement.allItemsRendered();
|
||||||
|
assertEquals(1, itemsRendered.length);
|
||||||
|
assertEquals(0, itemsRendered[0]);
|
||||||
|
assertEquals(0, testElement.shadowRoot!.querySelectorAll('.item').length);
|
||||||
|
});
|
||||||
|
});
|
@@ -38,6 +38,10 @@ IN_PROC_BROWSER_TEST_F(CrExtensionsTest, ActivityLogStreamItem) {
|
|||||||
RunTest("extensions/activity_log_stream_item_test.js", "mocha.run()");
|
RunTest("extensions/activity_log_stream_item_test.js", "mocha.run()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IN_PROC_BROWSER_TEST_F(CrExtensionsTest, AsyncMapDirective) {
|
||||||
|
RunTest("extensions/async_map_directive_test.js", "mocha.run()");
|
||||||
|
}
|
||||||
|
|
||||||
IN_PROC_BROWSER_TEST_F(CrExtensionsTest, ToggleRow) {
|
IN_PROC_BROWSER_TEST_F(CrExtensionsTest, ToggleRow) {
|
||||||
RunTest("extensions/toggle_row_test.js", "mocha.run()");
|
RunTest("extensions/toggle_row_test.js", "mocha.run()");
|
||||||
}
|
}
|
||||||
|
5
third_party/lit/v3_0/BUILD.gn
vendored
5
third_party/lit/v3_0/BUILD.gn
vendored
@@ -155,6 +155,11 @@ ts_library("build_ts") {
|
|||||||
path_mappings = [
|
path_mappings = [
|
||||||
"lit/index.js|" +
|
"lit/index.js|" +
|
||||||
rebase_path("${node_modules}/lit/index.d.ts", target_gen_dir),
|
rebase_path("${node_modules}/lit/index.d.ts", target_gen_dir),
|
||||||
|
"lit-html/async-directive.js|" +
|
||||||
|
rebase_path("${node_modules}/lit-html/async-directive.d.ts",
|
||||||
|
target_gen_dir),
|
||||||
|
"lit-html/directive.js|" +
|
||||||
|
rebase_path("${node_modules}/lit-html/directive.d.ts", target_gen_dir),
|
||||||
"lit-html|" +
|
"lit-html|" +
|
||||||
rebase_path("${node_modules}/lit-html/lit-html.d.ts", target_gen_dir),
|
rebase_path("${node_modules}/lit-html/lit-html.d.ts", target_gen_dir),
|
||||||
"@lit/reactive-element|" + rebase_path(
|
"@lit/reactive-element|" + rebase_path(
|
||||||
|
4
third_party/lit/v3_0/lit.ts
vendored
4
third_party/lit/v3_0/lit.ts
vendored
@@ -2,5 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
export {css, CSSResultGroup, html, LitElement, nothing, render, PropertyValues, TemplateResult} from 'lit/index.js';
|
export {css, CSSResultGroup, html, LitElement, noChange, nothing, render, PropertyValues, TemplateResult} from 'lit/index.js';
|
||||||
|
export {directive, DirectiveParameters, PartInfo, PartType} from 'lit-html/directive.js';
|
||||||
|
export {AsyncDirective, ChildPart} from 'lit-html/async-directive.js';
|
||||||
export {CrLitElement} from './cr_lit_element.js';
|
export {CrLitElement} from './cr_lit_element.js';
|
||||||
|
10
third_party/lit/v3_0/rollup.config.mjs
vendored
10
third_party/lit/v3_0/rollup.config.mjs
vendored
@@ -24,6 +24,10 @@ function plugin() {
|
|||||||
// URL mappings from bare import URLs to file paths.
|
// URL mappings from bare import URLs to file paths.
|
||||||
const redirects = new Map([
|
const redirects = new Map([
|
||||||
['lit/index.js', path.join(pathToNodeModules, 'lit/index.js')],
|
['lit/index.js', path.join(pathToNodeModules, 'lit/index.js')],
|
||||||
|
['lit-html/async-directive.js',
|
||||||
|
path.join(pathToNodeModules, 'lit-html/async-directive.js')],
|
||||||
|
['lit-html/directive.js',
|
||||||
|
path.join(pathToNodeModules, 'lit-html/directive.js')],
|
||||||
['lit-element/lit-element.js',
|
['lit-element/lit-element.js',
|
||||||
path.join(pathToNodeModules, 'lit-element/lit-element.js')],
|
path.join(pathToNodeModules, 'lit-element/lit-element.js')],
|
||||||
['lit-html/is-server.js',
|
['lit-html/is-server.js',
|
||||||
@@ -37,6 +41,12 @@ function plugin() {
|
|||||||
name: 'lit-path-resolver-plugin',
|
name: 'lit-path-resolver-plugin',
|
||||||
|
|
||||||
resolveId(source, origin) {
|
resolveId(source, origin) {
|
||||||
|
// Ensure all lit-html imports are de-duped so that this file is not
|
||||||
|
// included in the bundle twice.
|
||||||
|
if (source.endsWith('lit-html.js')) {
|
||||||
|
return path.join(pathToNodeModules, 'lit-html/lit-html.js');
|
||||||
|
}
|
||||||
|
|
||||||
if (source.startsWith('.')) {
|
if (source.startsWith('.')) {
|
||||||
// Let Rollup handle relative paths.
|
// Let Rollup handle relative paths.
|
||||||
return null;
|
return null;
|
||||||
|
5
third_party/node/lit_include.txt
vendored
5
third_party/node/lit_include.txt
vendored
@@ -7,8 +7,11 @@
|
|||||||
# Lit JS files.
|
# Lit JS files.
|
||||||
/lit-element/LICENSE
|
/lit-element/LICENSE
|
||||||
/lit-element/lit-element.js
|
/lit-element/lit-element.js
|
||||||
/lit-html/is-server.js
|
/lit-html/async-directive.js
|
||||||
|
/lit-html/directive.js
|
||||||
|
/lit-html/directive-helpers.js
|
||||||
/lit-html/lit-html.js
|
/lit-html/lit-html.js
|
||||||
|
/lit-html/is-server.js
|
||||||
/lit/index.js
|
/lit/index.js
|
||||||
/@lit/reactive-element/css-tag.js
|
/@lit/reactive-element/css-tag.js
|
||||||
/@lit/reactive-element/reactive-element.js
|
/@lit/reactive-element/reactive-element.js
|
||||||
|
2
third_party/node/node_modules.tar.gz.sha1
vendored
2
third_party/node/node_modules.tar.gz.sha1
vendored
@@ -1 +1 @@
|
|||||||
a998f33a6d26e2a5bb38180bca2c03eacaf0d1a6
|
8eb0a40003464becccc4da796843e35116d0aa2e
|
||||||
|
Reference in New Issue
Block a user