From 89801b1149b18c580a4fee6563638a8883fad2d1 Mon Sep 17 00:00:00 2001 From: Daniel Leroux Date: Tue, 17 Dec 2024 15:12:29 +0100 Subject: [PATCH] feat(core): prevent define icons by library (#1609) Co-authored-by: Lukas Maurer --- .changeset/khaki-moles-cry.md | 11 ++++ packages/core/playwright-ct.config.ts | 2 +- packages/core/src/index.html | 1 + packages/core/src/setup.ct.ts | 21 +++++++ packages/core/src/setup.ts | 20 +++++-- packages/core/src/tests/utils/ct/index.html | 2 - packages/core/src/tests/utils/test/page.ts | 56 ++++++++++++++----- .../docs/installation/javascript.md | 10 ++++ 8 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 .changeset/khaki-moles-cry.md create mode 100644 packages/core/src/setup.ct.ts diff --git a/.changeset/khaki-moles-cry.md b/.changeset/khaki-moles-cry.md new file mode 100644 index 0000000000..8a7680e98a --- /dev/null +++ b/.changeset/khaki-moles-cry.md @@ -0,0 +1,11 @@ +--- +'@siemens/ix': minor +--- + +Add `meta`-tag feature to disable default load of `@siemens/ix-icons` + +```html + +``` + +In addition the warning is removed if no icon component is provided. diff --git a/packages/core/playwright-ct.config.ts b/packages/core/playwright-ct.config.ts index 59ba8c6da3..7b6c6ccc92 100644 --- a/packages/core/playwright-ct.config.ts +++ b/packages/core/playwright-ct.config.ts @@ -18,7 +18,7 @@ import defaultConfig from './playwright.config'; /** @type {import('@playwright/test').PlaywrightTestConfig} */ const config: PlaywrightTestConfig = { ...defaultConfig, - testMatch: path.join(__dirname, 'src', 'components', '**', '*.ct.ts'), + testMatch: path.join(__dirname, 'src', '**', '*.ct.ts'), reporter: 'list', projects: [ { diff --git a/packages/core/src/index.html b/packages/core/src/index.html index 985e9627f1..b909a69f94 100644 --- a/packages/core/src/index.html +++ b/packages/core/src/index.html @@ -12,6 +12,7 @@ name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0" /> + Stencil Component Starter diff --git a/packages/core/src/setup.ct.ts b/packages/core/src/setup.ct.ts new file mode 100644 index 0000000000..54f98f6c8b --- /dev/null +++ b/packages/core/src/setup.ct.ts @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2024 Siemens AG + * + * SPDX-License-Identifier: MIT + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import { expect } from '@playwright/test'; +import { test } from '@utils/test'; + +test('should not define icons if meta tag is set to false', async ({ + page, + mount, +}) => { + await mount(``, { + headTags: [''], + }); + await page.waitForTimeout(1000); + await expect(page.locator('ix-icon')).not.toBeVisible(); +}); diff --git a/packages/core/src/setup.ts b/packages/core/src/setup.ts index b5e4a99c58..727e43e16d 100644 --- a/packages/core/src/setup.ts +++ b/packages/core/src/setup.ts @@ -9,20 +9,32 @@ import { setPlatformHelpers } from '@stencil/core'; +export function shouldDefineIcons(): boolean { + const content = document.head + ?.querySelector('meta[name="ix:legacy-icons"]') + ?.getAttribute('content'); + + if (!content) { + return true; + } + + return content.toLowerCase() === 'true'; +} + async function setupIcons() { if (typeof window === 'undefined') { return; } + if (shouldDefineIcons() === false) { + return; + } + const iconComponent = window.customElements.get('ix-icon'); if (iconComponent) { return; } - console.warn( - 'ix-icon web component not loaded. Using local fallback version' - ); - const ixIcons = await import('@siemens/ix-icons/loader'); await ixIcons.defineCustomElements(); } diff --git a/packages/core/src/tests/utils/ct/index.html b/packages/core/src/tests/utils/ct/index.html index baa5bf813c..625c946688 100644 --- a/packages/core/src/tests/utils/ct/index.html +++ b/packages/core/src/tests/utils/ct/index.html @@ -21,7 +21,5 @@
- - diff --git a/packages/core/src/tests/utils/test/page.ts b/packages/core/src/tests/utils/test/page.ts index 9d53beb8ec..6209025dea 100644 --- a/packages/core/src/tests/utils/test/page.ts +++ b/packages/core/src/tests/utils/test/page.ts @@ -54,21 +54,49 @@ export const test = testBase.extend({ await page.goto( `http://127.0.0.1:8080/src/tests/utils/ct/index.html?theme=${theme}` ); - use((selector: string) => { - return page.evaluateHandle( - async ({ componentSelector }) => { - await window.customElements.whenDefined('ix-button'); - const mount = document.querySelector('#mount'); + use( + ( + selector: string, + config?: { + headTags?: string[]; + } + ) => { + return page.evaluateHandle( + async ({ componentSelector, config }) => { + if (config?.headTags) { + config.headTags.forEach((tag) => { + const head = document.querySelector('head'); + if (!head) { + throw new Error('No head tag found in the document.'); + } - if (!mount) { - throw new Error('No mount point found in the document.'); - } + head.innerHTML += tag; + }); + } - mount.innerHTML = componentSelector; - return mount.children.item(0) as HTMLElement; - }, - { componentSelector: selector } - ); - }); + const loadScript = document.createElement('script'); + loadScript.src = '/scripts/e2e/load-e2e-runtime.js'; + document.body.appendChild(loadScript); + + await new Promise((resolve) => { + loadScript.onload = async () => { + resolve(); + }; + }); + + await window.customElements.whenDefined('ix-button'); + const mount = document.querySelector('#mount'); + + if (!mount) { + throw new Error('No mount point found in the document.'); + } + + mount.innerHTML = componentSelector; + return mount.children.item(0) as HTMLElement; + }, + { componentSelector: selector, config } + ); + } + ); }, }); diff --git a/packages/documentation/docs/installation/javascript.md b/packages/documentation/docs/installation/javascript.md index 5a34258a75..317d93f754 100644 --- a/packages/documentation/docs/installation/javascript.md +++ b/packages/documentation/docs/installation/javascript.md @@ -67,6 +67,16 @@ import { defineCustomElements as defineIxIconCustomElement } from '@siemens/ix-i })(); ``` +## Prevent `@siemens/ix-icons` to be defined during library load + +> This can be useful if you have configured CSP nonce, because of the lazy bootstrap behavior of the components. + +To prevent the definition of the `ix-icon` component during library setup, add the following `````` HTML element to your application: + +```html + +``` + ## Example