From d236206cce957fc3beaa460b1de316538289f2a5 Mon Sep 17 00:00:00 2001 From: konnorrogers Date: Mon, 12 Jun 2023 10:54:33 -0400 Subject: [PATCH 01/15] remove unneeded CLI args --- .gitignore | 1 + package.json | 7 ++-- scripts/build.js | 83 +++++++++++++++++++++++++++++++++--------------- 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index eab31735..24a14172 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dist docs/assets/images/sprite.svg node_modules src/react +cdn diff --git a/package.json b/package.json index bbcebe6c..c6355ded 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "./dist/translations/*": "./dist/translations/*" }, "files": [ - "dist" + "dist", + "cdn" ], "keywords": [ "web components", @@ -42,8 +43,8 @@ "url": "https://github.com/sponsors/claviska" }, "scripts": { - "start": "node scripts/build.js --bundle --serve", - "build": "node scripts/build.js --bundle --types --copydir \"_site/dist\"", + "start": "node scripts/build.js --serve", + "build": "node scripts/build.js", "verify": "npm run prettier:check && npm run lint && npm run build && npm run test", "prepublishOnly": "npm run verify", "prettier": "prettier --write --loglevel warn .", diff --git a/scripts/build.js b/scripts/build.js index bc2eff0f..7abc1766 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -11,18 +11,19 @@ import getPort, { portNumbers } from 'get-port'; import ora from 'ora'; import util from 'util'; -const { bundle, copydir, dir, serve, types } = commandLineArgs([ - { name: 'bundle', type: Boolean }, +const { copydir, serve } = commandLineArgs([ { name: 'copydir', type: String }, { name: 'serve', type: Boolean }, - { name: 'types', type: Boolean } ]); const outdir = 'dist'; +const cdndir = 'cdn' const sitedir = '_site'; const spinner = ora({ hideCursor: false }).start(); const execPromise = util.promisify(exec); let childProcess; -let buildResult; +let buildResults; + +const bundleDirectories = [cdndir, outdir] // // Runs 11ty and builds the docs. The returned promise resolves after the initial publish has completed. The child @@ -72,7 +73,15 @@ async function buildTheDocs(watch = false) { async function buildTheSource() { const alwaysExternal = ['@lit-labs/react', 'react']; - return await esbuild.build({ + const packageJSON = await fs.readFile("./package.json") + const dependencies = [ + ...Object.keys(packageJSON.dependencies || {}), + ...Object.keys(packageJSON.peerDependencies || {}) + ] + + const allExternal = [...alwaysExternal, ...dependencies] + + const cdnConfig = { format: 'esm', target: 'es2017', entryPoints: [ @@ -94,7 +103,7 @@ async function buildTheSource() { // React wrappers ...(await globby('./src/react/**/*.ts')) ], - outdir, + outdir: cdndir, chunkNames: 'chunks/[name].[hash]', incremental: serve, define: { @@ -108,19 +117,29 @@ async function buildTheSource() { // // We never bundle React or @lit-labs/react though! // - external: bundle - ? alwaysExternal - : [...alwaysExternal, '@floating-ui/dom', '@shoelace-style/animations', 'lit', 'qr-creator'], + external: alwaysExternal, splitting: true, plugins: [] - }); + } + + const npmConfig = { + ...cdnConfig, + external: allExternal, + outdir + } + + + return await Promise.all([ + esbuild.build(cdnConfig), + esbuild.build(npmConfig) + ]) } // // Called on SIGINT or SIGTERM to cleanup the build and child processes. // function handleCleanup() { - buildResult.rebuild.dispose(); + buildResults.forEach((result) => result.rebuild.dispose()); if (childProcess) { childProcess.kill('SIGINT'); @@ -150,12 +169,16 @@ async function nextTask(label, action) { } await nextTask('Cleaning up the previous build', async () => { - await Promise.all([deleteAsync(outdir), deleteAsync(sitedir)]); + await Promise.all([deleteAsync(sitedir), ...bundleDirectories.map((dir) => deleteAsync(dir))]); await fs.mkdir(outdir, { recursive: true }); }); await nextTask('Generating component metadata', () => { - return execPromise(`node scripts/make-metadata.js --outdir "${outdir}"`, { stdio: 'inherit' }); + return Promise.all( + bundleDirectories.map((dir) => { + return execPromise(`node scripts/make-metadata.js --outdir "${dir}"`, { stdio: 'inherit' }) + }) + ) }); await nextTask('Wrapping components for React', () => { @@ -178,17 +201,23 @@ await nextTask('Running the TypeScript compiler', () => { return execPromise(`tsc --project ./tsconfig.prod.json --outdir "${outdir}"`, { stdio: 'inherit' }); }); -await nextTask('Building source files', async () => { - buildResult = await buildTheSource(); +// Copy the above steps to the CDN directory directly so we dont need to twice the work for nothing. +await nextTask(`Copying Web Types, Themes, Icons, and TS Types to "${cdndir}"`, async () => { + await deleteAsync(cdndir); + await copy(outdir, cdndir); }); -if (copydir) { - // Copy the build output to an additional directory - await nextTask(`Copying the build to "${copydir}"`, async () => { - await deleteAsync(copydir); - await copy(outdir, copydir); - }); -} +await nextTask('Building source files', async () => { + buildResults = await buildTheSource(); +}); + +// Copy the build output to the documentation dist directory +await nextTask(`Copying the build to "${sitedir}"`, async () => { + await deleteAsync(sitedir); + + // We copy the CDN build because that has everything bundled. + await copy(cdndir, sitedir); +}); // Launch the dev server if (serve) { @@ -243,16 +272,20 @@ if (serve) { const isStylesheet = /(\.css|\.styles\.ts)$/.test(filename); // Rebuild the source - await buildResult.rebuild(); + await Promise.all([buildResults.map((result) => result.rebuild())]); // Rebuild stylesheets when a theme file changes if (isTheme) { - await execPromise(`node scripts/make-themes.js --outdir "${outdir}"`, { stdio: 'inherit' }); + await Promise.all(bundleDirectories.map((dir) => { + execPromise(`node scripts/make-themes.js --outdir "${dir}"`, { stdio: 'inherit' }); + })) } // Rebuild metadata (but not when styles are changed) if (!isStylesheet) { - await execPromise(`node scripts/make-metadata.js --outdir "${outdir}"`, { stdio: 'inherit' }); + await Promise.all(bundleDirectories.map((dir) => { + return execPromise(`node scripts/make-metadata.js --outdir "${dir}"`, { stdio: 'inherit' }); + })) } bs.reload(); From 96daee5e1ab7e7e0abc6b8aff7696f5957e1654a Mon Sep 17 00:00:00 2001 From: konnorrogers Date: Mon, 12 Jun 2023 11:18:24 -0400 Subject: [PATCH 02/15] use cdn dir for testing --- web-test-runner.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web-test-runner.config.js b/web-test-runner.config.js index b273756b..c9dc5670 100644 --- a/web-test-runner.config.js +++ b/web-test-runner.config.js @@ -28,8 +28,8 @@ export default { - - + + From 415a1477bb55f1025eda8490682eef11e26c95cc Mon Sep 17 00:00:00 2001 From: konnorrogers Date: Mon, 12 Jun 2023 11:39:56 -0400 Subject: [PATCH 03/15] changelog, prettier --- docs/pages/resources/changelog.md | 1 + scripts/build.js | 50 +++++++++++++++---------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md index 0439313f..728b743b 100644 --- a/docs/pages/resources/changelog.md +++ b/docs/pages/resources/changelog.md @@ -14,6 +14,7 @@ New versions of Shoelace are released as-needed and generally occur when a criti ## Next +- Added a `cdn/` path for bundled dependencies. Imports for NPM users will remain the same. [#1369](https://github.com/shoelace-style/shoelace/pull/1369) - Added the `checkbox` part and related exported parts to `` so you can target it with CSS [#1318](https://github.com/shoelace-style/shoelace/discussions/1318) - Added the `submenu-icon` part to `` (submenus have not been implemented yet, but this part is required to allow customizations) - Added tests for `` [#1343](https://github.com/shoelace-style/shoelace/pull/1343) diff --git a/scripts/build.js b/scripts/build.js index 7abc1766..179a1a2b 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -13,17 +13,17 @@ import util from 'util'; const { copydir, serve } = commandLineArgs([ { name: 'copydir', type: String }, - { name: 'serve', type: Boolean }, + { name: 'serve', type: Boolean } ]); const outdir = 'dist'; -const cdndir = 'cdn' +const cdndir = 'cdn'; const sitedir = '_site'; const spinner = ora({ hideCursor: false }).start(); const execPromise = util.promisify(exec); let childProcess; let buildResults; -const bundleDirectories = [cdndir, outdir] +const bundleDirectories = [cdndir, outdir]; // // Runs 11ty and builds the docs. The returned promise resolves after the initial publish has completed. The child @@ -73,13 +73,13 @@ async function buildTheDocs(watch = false) { async function buildTheSource() { const alwaysExternal = ['@lit-labs/react', 'react']; - const packageJSON = await fs.readFile("./package.json") + const packageJSON = await fs.readFile('./package.json'); const dependencies = [ ...Object.keys(packageJSON.dependencies || {}), ...Object.keys(packageJSON.peerDependencies || {}) - ] + ]; - const allExternal = [...alwaysExternal, ...dependencies] + const allExternal = [...alwaysExternal, ...dependencies]; const cdnConfig = { format: 'esm', @@ -120,26 +120,22 @@ async function buildTheSource() { external: alwaysExternal, splitting: true, plugins: [] - } + }; const npmConfig = { ...cdnConfig, external: allExternal, outdir - } + }; - - return await Promise.all([ - esbuild.build(cdnConfig), - esbuild.build(npmConfig) - ]) + return await Promise.all([esbuild.build(cdnConfig), esbuild.build(npmConfig)]); } // // Called on SIGINT or SIGTERM to cleanup the build and child processes. // function handleCleanup() { - buildResults.forEach((result) => result.rebuild.dispose()); + buildResults.forEach(result => result.rebuild.dispose()); if (childProcess) { childProcess.kill('SIGINT'); @@ -169,16 +165,16 @@ async function nextTask(label, action) { } await nextTask('Cleaning up the previous build', async () => { - await Promise.all([deleteAsync(sitedir), ...bundleDirectories.map((dir) => deleteAsync(dir))]); + await Promise.all([deleteAsync(sitedir), ...bundleDirectories.map(dir => deleteAsync(dir))]); await fs.mkdir(outdir, { recursive: true }); }); await nextTask('Generating component metadata', () => { return Promise.all( - bundleDirectories.map((dir) => { - return execPromise(`node scripts/make-metadata.js --outdir "${dir}"`, { stdio: 'inherit' }) + bundleDirectories.map(dir => { + return execPromise(`node scripts/make-metadata.js --outdir "${dir}"`, { stdio: 'inherit' }); }) - ) + ); }); await nextTask('Wrapping components for React', () => { @@ -272,20 +268,24 @@ if (serve) { const isStylesheet = /(\.css|\.styles\.ts)$/.test(filename); // Rebuild the source - await Promise.all([buildResults.map((result) => result.rebuild())]); + await Promise.all([buildResults.map(result => result.rebuild())]); // Rebuild stylesheets when a theme file changes if (isTheme) { - await Promise.all(bundleDirectories.map((dir) => { - execPromise(`node scripts/make-themes.js --outdir "${dir}"`, { stdio: 'inherit' }); - })) + await Promise.all( + bundleDirectories.map(dir => { + execPromise(`node scripts/make-themes.js --outdir "${dir}"`, { stdio: 'inherit' }); + }) + ); } // Rebuild metadata (but not when styles are changed) if (!isStylesheet) { - await Promise.all(bundleDirectories.map((dir) => { - return execPromise(`node scripts/make-metadata.js --outdir "${dir}"`, { stdio: 'inherit' }); - })) + await Promise.all( + bundleDirectories.map(dir => { + return execPromise(`node scripts/make-metadata.js --outdir "${dir}"`, { stdio: 'inherit' }); + }) + ); } bs.reload(); From 68b982a74449dc775ddd3e1b0fd27eba23730d4b Mon Sep 17 00:00:00 2001 From: konnorrogers Date: Mon, 12 Jun 2023 12:48:15 -0400 Subject: [PATCH 04/15] update docs --- cspell.json | 1 + docs/_includes/component.njk | 18 ++++---- docs/assets/scripts/code-previews.js | 6 +-- docs/pages/frameworks/angular.md | 4 +- docs/pages/frameworks/react.md | 4 +- docs/pages/frameworks/vue-2.md | 4 +- docs/pages/frameworks/vue.md | 4 +- docs/pages/getting-started/installation.md | 48 ++++++++++++++++------ docs/pages/getting-started/themes.md | 4 +- docs/pages/index.md | 6 +-- 10 files changed, 61 insertions(+), 38 deletions(-) diff --git a/cspell.json b/cspell.json index bc92397a..6ca3c963 100644 --- a/cspell.json +++ b/cspell.json @@ -18,6 +18,7 @@ "CACHEABLE", "callout", "callouts", + "cdndir", "chatbubble", "checkmark", "claviska", diff --git a/docs/_includes/component.njk b/docs/_includes/component.njk index 8d65f7f8..d353b988 100644 --- a/docs/_includes/component.njk +++ b/docs/_includes/component.njk @@ -39,15 +39,15 @@ {% if component.summary %} {{ component.summary | markdownInline | safe }} {% endif %} -

- +

+ {# Markdown content #} {{ content | safe }} {# Importing #}

Importing

- If you're using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use + If you're using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.

@@ -59,18 +59,18 @@

- To import this component from the CDN + To import this component from the CDN using a script tag:

-
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/dist/{{ component.path }}"></script>
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/cdn/{{ component.path }}"></script>

- To import this component from the CDN + To import this component from the CDN using a JavaScript import:

-
import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/dist/{{ component.path }}';
+
import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/cdn/{{ component.path }}';
@@ -337,11 +337,11 @@

Dependencies

This component automatically imports the following dependencies.

- +
    {% for dependency in component.dependencies %}
  • <{{ dependency }}>
  • {% endfor %}
{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/docs/assets/scripts/code-previews.js b/docs/assets/scripts/code-previews.js index 40e11aa7..b7c26233 100644 --- a/docs/assets/scripts/code-previews.js +++ b/docs/assets/scripts/code-previews.js @@ -180,7 +180,7 @@ // HTML templates if (!isReact) { htmlTemplate = - `\n` + + `\n` + `\n${htmlExample}`; jsTemplate = ''; } @@ -191,7 +191,7 @@ jsTemplate = `import React from 'https://cdn.skypack.dev/react@${reactVersion}';\n` + `import ReactDOM from 'https://cdn.skypack.dev/react-dom@${reactVersion}';\n` + - `import { setBasePath } from 'https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/dist/utilities/base-path';\n` + + `import { setBasePath } from 'https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/cdn/utilities/base-path';\n` + `\n` + `// Set the base path for Shoelace assets\n` + `setBasePath('https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/dist/')\n` + @@ -202,7 +202,7 @@ // CSS templates cssTemplate = - `@import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${shoelaceVersion}/dist/themes/${ + `@import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${shoelaceVersion}/cdn/themes/${ isDark ? 'dark' : 'light' }.css';\n` + '\n' + diff --git a/docs/pages/frameworks/angular.md b/docs/pages/frameworks/angular.md index e604d484..b1ce5675 100644 --- a/docs/pages/frameworks/angular.md +++ b/docs/pages/frameworks/angular.md @@ -22,7 +22,7 @@ Next, [include a theme](/getting-started/themes) and set the [base path](/gettin import '@shoelace-style/shoelace/dist/themes/light.css'; import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path'; -setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/'); +setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/cdn/'); ``` :::tip @@ -85,4 +85,4 @@ Now you can start using Shoelace components in your app! :::tip Are you using Shoelace with Angular? [Help us improve this page!](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/angular.md) -::: +::: \ No newline at end of file diff --git a/docs/pages/frameworks/react.md b/docs/pages/frameworks/react.md index a46a2091..bab6d59e 100644 --- a/docs/pages/frameworks/react.md +++ b/docs/pages/frameworks/react.md @@ -23,7 +23,7 @@ Next, [include a theme](/getting-started/themes) and set the [base path](/gettin import '@shoelace-style/shoelace/dist/themes/light.css'; import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path'; -setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/'); +setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/cdn/'); ``` :::tip @@ -151,4 +151,4 @@ For more details, refer to Jest's [`transformIgnorePatterns` customization](http :::tip Are you using Shoelace with React? [Help us improve this page!](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/react.md) -::: +::: \ No newline at end of file diff --git a/docs/pages/frameworks/vue-2.md b/docs/pages/frameworks/vue-2.md index 45842ac5..c099c5de 100644 --- a/docs/pages/frameworks/vue-2.md +++ b/docs/pages/frameworks/vue-2.md @@ -26,7 +26,7 @@ Next, [include a theme](/getting-started/themes) and set the [base path](/gettin import '@shoelace-style/shoelace/dist/themes/light.css'; import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path'; -setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/'); +setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/cdn/'); ``` :::tip @@ -104,4 +104,4 @@ Now you can use the `v-sl-model` directive to keep your data in sync! :::tip Are you using Shoelace with Vue? [Help us improve this page!](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/vue-2.md) -::: +::: \ No newline at end of file diff --git a/docs/pages/frameworks/vue.md b/docs/pages/frameworks/vue.md index 88062b0c..3284a44f 100644 --- a/docs/pages/frameworks/vue.md +++ b/docs/pages/frameworks/vue.md @@ -26,7 +26,7 @@ Next, [include a theme](/getting-started/themes) and set the [base path](/gettin import '@shoelace-style/shoelace/dist/themes/light.css'; import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path'; -setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/'); +setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/cdn/'); ``` :::tip @@ -124,4 +124,4 @@ Here is an example: Close -``` +``` \ No newline at end of file diff --git a/docs/pages/getting-started/installation.md b/docs/pages/getting-started/installation.md index 6b423530..a1441dfa 100644 --- a/docs/pages/getting-started/installation.md +++ b/docs/pages/getting-started/installation.md @@ -22,8 +22,8 @@ While convenient, autoloading may lead to a [Flash of Undefined Custom Elements] ```html - - + + ```
@@ -33,8 +33,8 @@ While convenient, autoloading may lead to a [Flash of Undefined Custom Elements] The traditional CDN loader registers all Shoelace elements up front. Note that, if you're only using a handful of components, it will be much more efficient to stick with the autoloader. However, you can also [cherry pick](#cherry-picking) components if you want to load specific ones up front. ```html - - + + ``` @@ -45,7 +45,7 @@ The traditional CDN loader registers all Shoelace elements up front. Note that, The code above will load the light theme. If you want to use the [dark theme](/getting-started/themes#dark-theme) instead, update the stylesheet as shown below and add `` to your page. ```html - + ``` ### Light & Dark Theme @@ -56,21 +56,21 @@ If you want to load the light or dark theme based on the user's `prefers-color-s ``` Now you can [start using Shoelace!](/getting-started/usage) -## Local Installation +## NPM installation -If you don't want to use the CDN, you can install Shoelace locally with the following command. +If you don't want to use the CDN, you can install Shoelace from NPM with the following command. ```bash npm install @shoelace-style/shoelace @@ -110,20 +110,26 @@ However, if you're [cherry picking](#cherry-picking) or [bundling](#bundling) Sh ``` :::tip -The library also exports a `getBasePath()` method you can use to reference assets. +When setting a basePath, and easy way to check if it was down properly is by checking if an icon exists. + +For example, if I set the basePath to `/dist`, I should be able to go to: + +`https:///dist/assets/icons/arrow-left.svg` and the browser should show me the SVG. + +Shoelace also exports a `getBasePath()` method you can use to reference assets. ::: ## Cherry Picking -Cherry picking can be done from [the CDN](#cdn-installation-easiest) or your [local installation](#local-installation). This approach will load only the components you need up front, while limiting the number of files the browser has to download. The disadvantage is that you need to import each individual component. +Cherry picking can be done from [the CDN](#cdn-installation-easiest) or from [NPM](#npm-installation). This approach will load only the components you need up front, while limiting the number of files the browser has to download. The disadvantage is that you need to import each individual component. Here's an example that loads only the button component. Again, if you're not using a module resolver, you'll need to adjust the path to point to the folder Shoelace is in. ```html - + @@ -173,3 +179,19 @@ setBasePath('/path/to/shoelace/dist'); :::warning Component modules include side effects for registration purposes. Because of this, importing directly from `@shoelace-style/shoelace` may result in a larger bundle size than necessary. For optimal tree shaking, always cherry pick, i.e. import components and utilities from their respective files, as shown above. ::: + +## The difference between CDN and NPM + +You'll notice above that the CDN links all start with `/cdn/` and imports using NPM use `/dist/`. +The `/cdn` files use a different bundle from `/dist`. `/cdn` files come "prebundled" which means all dependencies are +inlined so you do not need to worry about loading any additional libraries. `/dist` does **NOT** prebundle dependencies +allowing for your bundler of choice to more efficiently deduplicate dependencies resulting in smaller overall bundles +and greater code sharing. + +TLDR: + +- `@shoelace-style/shoelace/cdn` is for CDN +- `@shoelace-style/shoelace/dist` is for NPM + +This change was introduced in `v2.5.0` to address issues around installations from NPM +loading multiple versions of libraries such as the Lit web component library which Shoelace uses internally. \ No newline at end of file diff --git a/docs/pages/getting-started/themes.md b/docs/pages/getting-started/themes.md index 1dd1508c..da35aa93 100644 --- a/docs/pages/getting-started/themes.md +++ b/docs/pages/getting-started/themes.md @@ -127,7 +127,7 @@ The dark theme works by taking the light theme's [color tokens](/tokens/color) a To install the dark theme, add the following to the `` section of your page. ```html - + ``` To activate the theme, apply the `sl-theme-dark` class to the `` element. @@ -146,4 +146,4 @@ Shoelace doesn't try to auto-detect the user's light/dark mode preference. This - Allow the user to override the setting in your app - Remember the user's preference and restore it on subsequent logins -Shoelace avoids using the `prefers-color-scheme` media query because not all apps support dark mode, and it would break things for the ones that don't. +Shoelace avoids using the `prefers-color-scheme` media query because not all apps support dark mode, and it would break things for the ones that don't. \ No newline at end of file diff --git a/docs/pages/index.md b/docs/pages/index.md index e9bf8fbc..c59e01d9 100644 --- a/docs/pages/index.md +++ b/docs/pages/index.md @@ -41,8 +41,8 @@ Add the following code to your page. ```html - - + + ``` Now you have access to all of Shoelace's components! Try adding a button: @@ -137,4 +137,4 @@ Special thanks to the following projects and individuals that help make Shoelace - Positioning of dropdowns, tooltips, et al is handled by [Floating UI](https://floating-ui.com/) - Animations are courtesy of [animate.css](https://animate.style/) - Search is powered by [Lunr](https://lunrjs.com/) -- The Shoelace logo was designed with a single shoelace by [Adam K Olson](https://twitter.com/adamkolson) +- The Shoelace logo was designed with a single shoelace by [Adam K Olson](https://twitter.com/adamkolson) \ No newline at end of file From 41913c8c58e9de826e3ad41d25e21b31c2959125 Mon Sep 17 00:00:00 2001 From: konnorrogers Date: Mon, 12 Jun 2023 13:45:27 -0400 Subject: [PATCH 05/15] update docs with cdn / npm paths --- cspell.json | 2 + docs/_includes/component.njk | 8 ++-- docs/_utilities/replacer.cjs | 20 ++++++++ docs/assets/scripts/code-previews.js | 8 ++-- docs/eleventy.config.cjs | 12 ++++- docs/pages/frameworks/angular.md | 8 ++-- docs/pages/frameworks/react.md | 16 +++---- docs/pages/frameworks/vue-2.md | 6 +-- docs/pages/frameworks/vue.md | 2 +- docs/pages/getting-started/installation.md | 54 +++++++++++----------- docs/pages/getting-started/localization.md | 6 +-- docs/pages/getting-started/themes.md | 10 ++-- docs/pages/index.md | 4 +- scripts/build.js | 2 +- 14 files changed, 95 insertions(+), 63 deletions(-) create mode 100644 docs/_utilities/replacer.cjs diff --git a/cspell.json b/cspell.json index 6ca3c963..e9be0135 100644 --- a/cspell.json +++ b/cspell.json @@ -105,6 +105,7 @@ "noopener", "noreferrer", "novalidate", + "npmdir", "outdir", "ParamagicDev", "peta", @@ -147,6 +148,7 @@ "textareas", "textfield", "tinycolor", + "TLDR", "transitionend", "treeitem", "Triaging", diff --git a/docs/_includes/component.njk b/docs/_includes/component.njk index d353b988..c74ff4f8 100644 --- a/docs/_includes/component.njk +++ b/docs/_includes/component.njk @@ -62,7 +62,7 @@ To import this component from the CDN using a script tag:

-
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/cdn/{{ component.path }}"></script>
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/{{ meta.cdndir }}/{{ component.path }}"></script>
@@ -70,21 +70,21 @@ To import this component from the CDN using a JavaScript import:

-
import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/cdn/{{ component.path }}';
+
import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/{{ meta.cdndir }}/{{ component.path }}';

To import this component using a bundler:

-
import '@shoelace-style/shoelace/dist/{{ component.path }}';
+
import '@shoelace-style/shoelace/{{ meta.npmdir }}/{{ component.path }}';

To import this component as a React component:

-
import { {{ component.name }} } from '@shoelace-style/shoelace/dist/react';
+
import { {{ component.name }} } from '@shoelace-style/shoelace/{{ meta.npmdir }}/react';
diff --git a/docs/_utilities/replacer.cjs b/docs/_utilities/replacer.cjs new file mode 100644 index 00000000..b9dc588e --- /dev/null +++ b/docs/_utilities/replacer.cjs @@ -0,0 +1,20 @@ +/** + * @typedef {object} Replacement + * @property {string | RegExp} pattern + * @property {string} replacement + */ + +/** + * @typedef {Array} Replacements + */ + + +/** + * @param {Document} content + * @param {Replacements} replacements + */ +module.exports = function (content, replacements) { + replacements.forEach((replacement) => { + content.body.innerHTML = content.body.innerHTML.replaceAll(replacement.pattern, replacement.replacement) + }) +} diff --git a/docs/assets/scripts/code-previews.js b/docs/assets/scripts/code-previews.js index b7c26233..1995c408 100644 --- a/docs/assets/scripts/code-previews.js +++ b/docs/assets/scripts/code-previews.js @@ -180,7 +180,7 @@ // HTML templates if (!isReact) { htmlTemplate = - `\n` + + `\n` + `\n${htmlExample}`; jsTemplate = ''; } @@ -191,10 +191,10 @@ jsTemplate = `import React from 'https://cdn.skypack.dev/react@${reactVersion}';\n` + `import ReactDOM from 'https://cdn.skypack.dev/react-dom@${reactVersion}';\n` + - `import { setBasePath } from 'https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/cdn/utilities/base-path';\n` + + `import { setBasePath } from 'https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/%CDNDIR%/utilities/base-path';\n` + `\n` + `// Set the base path for Shoelace assets\n` + - `setBasePath('https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/dist/')\n` + + `setBasePath('https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/%NPMDIR%/')\n` + `\n${convertModuleLinks(reactExample)}\n` + `\n` + `ReactDOM.render(, document.getElementById('root'));`; @@ -202,7 +202,7 @@ // CSS templates cssTemplate = - `@import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${shoelaceVersion}/cdn/themes/${ + `@import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${shoelaceVersion}/%CDNDIR%/themes/${ isDark ? 'dark' : 'light' }.css';\n` + '\n' + diff --git a/docs/eleventy.config.cjs b/docs/eleventy.config.cjs index a1df2e60..f165bd6c 100644 --- a/docs/eleventy.config.cjs +++ b/docs/eleventy.config.cjs @@ -16,8 +16,11 @@ const tableOfContents = require('./_utilities/table-of-contents.cjs'); const prettier = require('./_utilities/prettier.cjs'); const scrollingTables = require('./_utilities/scrolling-tables.cjs'); const typography = require('./_utilities/typography.cjs'); +const replacer = require('./_utilities/replacer.cjs'); const assetsDir = 'assets'; +const cdndir = 'cdn' +const npmdir = 'dist' const allComponents = getAllComponents(); let hasBuiltSearchIndex = false; @@ -33,7 +36,9 @@ module.exports = function (eleventyConfig) { description: 'A forward-thinking library of web components.', image: 'images/og-image.png', version: customElementsManifest.package.version, - components: allComponents + components: allComponents, + cdndir, + npmdir }); // @@ -129,6 +134,11 @@ module.exports = function (eleventyConfig) { scrollingTables(doc); copyCodeButtons(doc); // must be after codePreviews + highlightCodeBlocks typography(doc, '#content'); + replacer(doc, [ + {pattern: "%VERSION%", replacement: customElementsManifest.package.version}, + {pattern: "%CDNDIR%", replacement: cdndir}, + {pattern: "%NPMDIR%", replacement: npmdir} + ]) // Serialize the Document object to an HTML string and prepend the doctype content = `\n${doc.documentElement.outerHTML}`; diff --git a/docs/pages/frameworks/angular.md b/docs/pages/frameworks/angular.md index b1ce5675..8b651132 100644 --- a/docs/pages/frameworks/angular.md +++ b/docs/pages/frameworks/angular.md @@ -19,14 +19,14 @@ npm install @shoelace-style/shoelace Next, [include a theme](/getting-started/themes) and set the [base path](/getting-started/installation#setting-the-base-path) for icons and other assets. In this example, we'll import the light theme and use the CDN as a base path. ```jsx -import '@shoelace-style/shoelace/dist/themes/light.css'; -import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path'; +import '@shoelace-style/shoelace/%NPMDIR%/themes/light.css'; +import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path'; -setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/cdn/'); +setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/'); ``` :::tip -If you'd rather not use the CDN for assets, you can create a build task that copies `node_modules/@shoelace-style/shoelace/dist/assets` into a public folder in your app. Then you can point the base path to that folder instead. +If you'd rather not use the CDN for assets, you can create a build task that copies `node_modules/@shoelace-style/shoelace/%NPMDIR%/assets` into a public folder in your app. Then you can point the base path to that folder instead. ::: ## Configuration diff --git a/docs/pages/frameworks/react.md b/docs/pages/frameworks/react.md index bab6d59e..080a77c0 100644 --- a/docs/pages/frameworks/react.md +++ b/docs/pages/frameworks/react.md @@ -20,14 +20,14 @@ Next, [include a theme](/getting-started/themes) and set the [base path](/gettin ```jsx // App.jsx -import '@shoelace-style/shoelace/dist/themes/light.css'; -import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path'; +import '@shoelace-style/shoelace/%NPMDIR%/themes/light.css'; +import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path'; -setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/cdn/'); +setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/'); ``` :::tip -If you'd rather not use the CDN for assets, you can create a [build task](https://webpack.js.org/plugins/copy-webpack-plugin/) that copies `node_modules/@shoelace-style/shoelace/dist/assets` into your app's `public` directory. Then you can point the base path to that folder instead. +If you'd rather not use the CDN for assets, you can create a [build task](https://webpack.js.org/plugins/copy-webpack-plugin/) that copies `node_modules/@shoelace-style/shoelace/%NPMDIR%/assets` into your app's `public` directory. Then you can point the base path to that folder instead. ::: Now you can start using components! @@ -39,7 +39,7 @@ Now you can start using components! Every Shoelace component is available to import as a React component. Note that we're importing the `` _React component_ instead of the `` _custom element_ in the example below. ```jsx -import { SlButton } from '@shoelace-style/shoelace/dist/react'; +import { SlButton } from '@shoelace-style/shoelace/%NPMDIR%/react'; const MyComponent = () => Click me; @@ -56,7 +56,7 @@ Here's how you can bind the input's value to a state variable. ```jsx import { useState } from 'react'; -import { SlInput } from '@shoelace-style/shoelace/dist/react'; +import { SlInput } from '@shoelace-style/shoelace/%NPMDIR%/react'; function MyComponent() { const [value, setValue] = useState(''); @@ -71,8 +71,8 @@ If you're using TypeScript, it's important to note that `event.target` will be a ```tsx import { useState } from 'react'; -import { SlInput } from '@shoelace-style/shoelace/dist/react'; -import type SlInputElement from '@shoelace-style/shoelace/dist/components/input/input'; +import { SlInput } from '@shoelace-style/shoelace/%NPMDIR%/react'; +import type SlInputElement from '@shoelace-style/shoelace/%NPMDIR%/components/input/input'; function MyComponent() { const [value, setValue] = useState(''); diff --git a/docs/pages/frameworks/vue-2.md b/docs/pages/frameworks/vue-2.md index c099c5de..992f6d6e 100644 --- a/docs/pages/frameworks/vue-2.md +++ b/docs/pages/frameworks/vue-2.md @@ -23,10 +23,10 @@ npm install @shoelace-style/shoelace Next, [include a theme](/getting-started/themes) and set the [base path](/getting-started/installation#setting-the-base-path) for icons and other assets. In this example, we'll import the light theme and use the CDN as a base path. ```jsx -import '@shoelace-style/shoelace/dist/themes/light.css'; -import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path'; +import '@shoelace-style/shoelace/%NPMDIR%/themes/light.css'; +import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path'; -setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/cdn/'); +setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/'); ``` :::tip diff --git a/docs/pages/frameworks/vue.md b/docs/pages/frameworks/vue.md index 3284a44f..08dae60e 100644 --- a/docs/pages/frameworks/vue.md +++ b/docs/pages/frameworks/vue.md @@ -26,7 +26,7 @@ Next, [include a theme](/getting-started/themes) and set the [base path](/gettin import '@shoelace-style/shoelace/dist/themes/light.css'; import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path'; -setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/cdn/'); +setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/'); ``` :::tip diff --git a/docs/pages/getting-started/installation.md b/docs/pages/getting-started/installation.md index a1441dfa..056cec41 100644 --- a/docs/pages/getting-started/installation.md +++ b/docs/pages/getting-started/installation.md @@ -22,8 +22,8 @@ While convenient, autoloading may lead to a [Flash of Undefined Custom Elements] ```html - - + + ``` @@ -33,8 +33,8 @@ While convenient, autoloading may lead to a [Flash of Undefined Custom Elements] The traditional CDN loader registers all Shoelace elements up front. Note that, if you're only using a handful of components, it will be much more efficient to stick with the autoloader. However, you can also [cherry pick](#cherry-picking) components if you want to load specific ones up front. ```html - - + + ``` @@ -45,7 +45,7 @@ The traditional CDN loader registers all Shoelace elements up front. Note that, The code above will load the light theme. If you want to use the [dark theme](/getting-started/themes#dark-theme) instead, update the stylesheet as shown below and add `` to your page. ```html - + ``` ### Light & Dark Theme @@ -56,12 +56,12 @@ If you want to load the light or dark theme based on the user's `prefers-color-s ``` @@ -81,8 +81,8 @@ It's up to you to make the source files available to your app. One way to do thi Once you've done that, add the following tags to your page. Make sure to update `href` and `src` so they point to the route you created. ```html - - + + ``` Alternatively, [you can use a bundler](#bundling). @@ -99,13 +99,13 @@ However, if you're [cherry picking](#cherry-picking) or [bundling](#bundling) Sh ```html - + ``` @@ -126,10 +126,10 @@ Cherry picking can be done from [the CDN](#cdn-installation-easiest) or from [NP Here's an example that loads only the button component. Again, if you're not using a module resolver, you'll need to adjust the path to point to the folder Shoelace is in. ```html - + - @@ -163,15 +163,15 @@ Now it's time to configure your bundler. Configurations vary for each tool, but Once your bundler is configured, you'll be able to import Shoelace components and utilities. ```js -import '@shoelace-style/shoelace/dist/themes/light.css'; -import '@shoelace-style/shoelace/dist/components/button/button.js'; -import '@shoelace-style/shoelace/dist/components/icon/icon.js'; -import '@shoelace-style/shoelace/dist/components/input/input.js'; -import '@shoelace-style/shoelace/dist/components/rating/rating.js'; -import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js'; +import '@shoelace-style/shoelace/%NPMDIR%/themes/light.css'; +import '@shoelace-style/shoelace/%NPMDIR%/components/button/button.js'; +import '@shoelace-style/shoelace/%NPMDIR%/components/icon/icon.js'; +import '@shoelace-style/shoelace/%NPMDIR%/components/input/input.js'; +import '@shoelace-style/shoelace/%NPMDIR%/components/rating/rating.js'; +import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path.js'; // Set the base path to the folder you copied Shoelace's assets to -setBasePath('/path/to/shoelace/dist'); +setBasePath('/path/to/shoelace/%NPMDIR% // , , , and are ready to use! ``` @@ -182,16 +182,16 @@ Component modules include side effects for registration purposes. Because of thi ## The difference between CDN and NPM -You'll notice above that the CDN links all start with `/cdn/` and imports using NPM use `/dist/`. -The `/cdn` files use a different bundle from `/dist`. `/cdn` files come "prebundled" which means all dependencies are -inlined so you do not need to worry about loading any additional libraries. `/dist` does **NOT** prebundle dependencies +You'll notice above that the CDN links all start with `/%CDNDIR%/` and imports using NPM use `/%NPMDIR%/`. +The `/%CDNDIR%` files use a different bundle from `/%NPMDIR%`. `/%CDNDIR%` files come "pre-bundled" which means all dependencies are +inlined so you do not need to worry about loading any additional libraries. `/%NPMDIR%` does **NOT** pre-bundle dependencies allowing for your bundler of choice to more efficiently deduplicate dependencies resulting in smaller overall bundles and greater code sharing. TLDR: -- `@shoelace-style/shoelace/cdn` is for CDN -- `@shoelace-style/shoelace/dist` is for NPM +- `@shoelace-style/shoelace/%CDNDIR%` is for CDN +- `@shoelace-style/shoelace/%NPMDIR%` is for NPM This change was introduced in `v2.5.0` to address issues around installations from NPM loading multiple versions of libraries such as the Lit web component library which Shoelace uses internally. \ No newline at end of file diff --git a/docs/pages/getting-started/localization.md b/docs/pages/getting-started/localization.md index 6dcdfcfb..2470558d 100644 --- a/docs/pages/getting-started/localization.md +++ b/docs/pages/getting-started/localization.md @@ -28,8 +28,8 @@ Shoelace ships with a number of translations. The default is English (US), which The location of translations depends on how you're consuming Shoelace. -- If you're using the CDN, [import them from the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace?path=dist%2Ftranslations) -- If you're using a bundler, import them from `@shoelace-style/shoelace/dist/translations/[lang].js` +- If you're using the CDN, [import them from the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace?path=%CDNDIR%%2Ftranslations) +- If you're using a bundler, import them from `@shoelace-style/shoelace/%NPMDIR%/translations/[lang].js` You do not need to load translations up front. You can import them dynamically even after updating the `lang` attribute. Once a translation is registered, localized components will update automatically. @@ -135,4 +135,4 @@ Once your translation has been compiled to JavaScript, import it and activate it :::tip If your translation isn't working, make sure you're using the same localize module when importing `registerTranslation`. If you're using a different module, your translation won't be recognized. -::: +::: \ No newline at end of file diff --git a/docs/pages/getting-started/themes.md b/docs/pages/getting-started/themes.md index da35aa93..e139d6a7 100644 --- a/docs/pages/getting-started/themes.md +++ b/docs/pages/getting-started/themes.md @@ -11,7 +11,7 @@ Shoelace is designed to be highly customizable through pure CSS. Out of the box, A theme is nothing more than a stylesheet that uses the Shoelace API to define design tokens and apply custom styles to components. To create a theme, you will need a decent understanding of CSS, including [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) and the [`::part` selector](https://developer.mozilla.org/en-US/docs/Web/CSS/::part). :::tip -For component developers, built-in themes are also available as JavaScript modules that export [Lit CSSResult](https://lit.dev/docs/api/styles/#CSSResult) objects. You can find them in `dist/themes/*.styles.js`. +For component developers, built-in themes are also available as JavaScript modules that export [Lit CSSResult](https://lit.dev/docs/api/styles/#CSSResult) objects. You can find them in `%NPMDIR%/themes/*.styles.js`. ::: ## Theme Basics @@ -34,7 +34,7 @@ To activate a theme, import it and apply the theme's class to the `` eleme ```html - + @@ -54,8 +54,8 @@ You can activate themes on various containers throughout the page. This example ```html - - + + @@ -127,7 +127,7 @@ The dark theme works by taking the light theme's [color tokens](/tokens/color) a To install the dark theme, add the following to the `` section of your page. ```html - + ``` To activate the theme, apply the `sl-theme-dark` class to the `` element. diff --git a/docs/pages/index.md b/docs/pages/index.md index c59e01d9..1e09273a 100644 --- a/docs/pages/index.md +++ b/docs/pages/index.md @@ -41,8 +41,8 @@ Add the following code to your page. ```html - - + + ``` Now you have access to all of Shoelace's components! Try adding a button: diff --git a/scripts/build.js b/scripts/build.js index 179a1a2b..7daa28fe 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -197,7 +197,7 @@ await nextTask('Running the TypeScript compiler', () => { return execPromise(`tsc --project ./tsconfig.prod.json --outdir "${outdir}"`, { stdio: 'inherit' }); }); -// Copy the above steps to the CDN directory directly so we dont need to twice the work for nothing. +// Copy the above steps to the CDN directory directly so we don't need to twice the work for nothing. await nextTask(`Copying Web Types, Themes, Icons, and TS Types to "${cdndir}"`, async () => { await deleteAsync(cdndir); await copy(outdir, cdndir); From d18db9adfa50837a0e40f5cda3ee849e4e783673 Mon Sep 17 00:00:00 2001 From: konnorrogers Date: Mon, 12 Jun 2023 14:20:11 -0400 Subject: [PATCH 06/15] prettier --- docs/_utilities/replacer.cjs | 9 ++++----- docs/eleventy.config.cjs | 12 ++++++------ docs/pages/frameworks/angular.md | 2 +- docs/pages/frameworks/react.md | 2 +- docs/pages/frameworks/vue-2.md | 2 +- docs/pages/frameworks/vue.md | 2 +- docs/pages/getting-started/installation.md | 17 +++++++++++++---- docs/pages/getting-started/localization.md | 2 +- docs/pages/getting-started/themes.md | 7 +++++-- docs/pages/index.md | 2 +- 10 files changed, 34 insertions(+), 23 deletions(-) diff --git a/docs/_utilities/replacer.cjs b/docs/_utilities/replacer.cjs index b9dc588e..ddc4d4a3 100644 --- a/docs/_utilities/replacer.cjs +++ b/docs/_utilities/replacer.cjs @@ -8,13 +8,12 @@ * @typedef {Array} Replacements */ - /** * @param {Document} content * @param {Replacements} replacements */ module.exports = function (content, replacements) { - replacements.forEach((replacement) => { - content.body.innerHTML = content.body.innerHTML.replaceAll(replacement.pattern, replacement.replacement) - }) -} + replacements.forEach(replacement => { + content.body.innerHTML = content.body.innerHTML.replaceAll(replacement.pattern, replacement.replacement); + }); +}; diff --git a/docs/eleventy.config.cjs b/docs/eleventy.config.cjs index f165bd6c..228bee49 100644 --- a/docs/eleventy.config.cjs +++ b/docs/eleventy.config.cjs @@ -19,8 +19,8 @@ const typography = require('./_utilities/typography.cjs'); const replacer = require('./_utilities/replacer.cjs'); const assetsDir = 'assets'; -const cdndir = 'cdn' -const npmdir = 'dist' +const cdndir = 'cdn'; +const npmdir = 'dist'; const allComponents = getAllComponents(); let hasBuiltSearchIndex = false; @@ -135,10 +135,10 @@ module.exports = function (eleventyConfig) { copyCodeButtons(doc); // must be after codePreviews + highlightCodeBlocks typography(doc, '#content'); replacer(doc, [ - {pattern: "%VERSION%", replacement: customElementsManifest.package.version}, - {pattern: "%CDNDIR%", replacement: cdndir}, - {pattern: "%NPMDIR%", replacement: npmdir} - ]) + { pattern: '%VERSION%', replacement: customElementsManifest.package.version }, + { pattern: '%CDNDIR%', replacement: cdndir }, + { pattern: '%NPMDIR%', replacement: npmdir } + ]); // Serialize the Document object to an HTML string and prepend the doctype content = `\n${doc.documentElement.outerHTML}`; diff --git a/docs/pages/frameworks/angular.md b/docs/pages/frameworks/angular.md index 8b651132..9b0914f0 100644 --- a/docs/pages/frameworks/angular.md +++ b/docs/pages/frameworks/angular.md @@ -85,4 +85,4 @@ Now you can start using Shoelace components in your app! :::tip Are you using Shoelace with Angular? [Help us improve this page!](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/angular.md) -::: \ No newline at end of file +::: diff --git a/docs/pages/frameworks/react.md b/docs/pages/frameworks/react.md index 080a77c0..5084bd15 100644 --- a/docs/pages/frameworks/react.md +++ b/docs/pages/frameworks/react.md @@ -151,4 +151,4 @@ For more details, refer to Jest's [`transformIgnorePatterns` customization](http :::tip Are you using Shoelace with React? [Help us improve this page!](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/react.md) -::: \ No newline at end of file +::: diff --git a/docs/pages/frameworks/vue-2.md b/docs/pages/frameworks/vue-2.md index 992f6d6e..cb4f61ba 100644 --- a/docs/pages/frameworks/vue-2.md +++ b/docs/pages/frameworks/vue-2.md @@ -104,4 +104,4 @@ Now you can use the `v-sl-model` directive to keep your data in sync! :::tip Are you using Shoelace with Vue? [Help us improve this page!](https://github.com/shoelace-style/shoelace/blob/next/docs/frameworks/vue-2.md) -::: \ No newline at end of file +::: diff --git a/docs/pages/frameworks/vue.md b/docs/pages/frameworks/vue.md index 08dae60e..5a63d32d 100644 --- a/docs/pages/frameworks/vue.md +++ b/docs/pages/frameworks/vue.md @@ -124,4 +124,4 @@ Here is an example: Close -``` \ No newline at end of file +``` diff --git a/docs/pages/getting-started/installation.md b/docs/pages/getting-started/installation.md index 056cec41..11f4e806 100644 --- a/docs/pages/getting-started/installation.md +++ b/docs/pages/getting-started/installation.md @@ -33,8 +33,14 @@ While convenient, autoloading may lead to a [Flash of Undefined Custom Elements] The traditional CDN loader registers all Shoelace elements up front. Note that, if you're only using a handful of components, it will be much more efficient to stick with the autoloader. However, you can also [cherry pick](#cherry-picking) components if you want to load specific ones up front. ```html - - + + ``` @@ -45,7 +51,10 @@ The traditional CDN loader registers all Shoelace elements up front. Note that, The code above will load the light theme. If you want to use the [dark theme](/getting-started/themes#dark-theme) instead, update the stylesheet as shown below and add `` to your page. ```html - + ``` ### Light & Dark Theme @@ -194,4 +203,4 @@ TLDR: - `@shoelace-style/shoelace/%NPMDIR%` is for NPM This change was introduced in `v2.5.0` to address issues around installations from NPM -loading multiple versions of libraries such as the Lit web component library which Shoelace uses internally. \ No newline at end of file +loading multiple versions of libraries such as the Lit web component library which Shoelace uses internally. diff --git a/docs/pages/getting-started/localization.md b/docs/pages/getting-started/localization.md index 2470558d..4555adde 100644 --- a/docs/pages/getting-started/localization.md +++ b/docs/pages/getting-started/localization.md @@ -135,4 +135,4 @@ Once your translation has been compiled to JavaScript, import it and activate it :::tip If your translation isn't working, make sure you're using the same localize module when importing `registerTranslation`. If you're using a different module, your translation won't be recognized. -::: \ No newline at end of file +::: diff --git a/docs/pages/getting-started/themes.md b/docs/pages/getting-started/themes.md index e139d6a7..7e725b7e 100644 --- a/docs/pages/getting-started/themes.md +++ b/docs/pages/getting-started/themes.md @@ -127,7 +127,10 @@ The dark theme works by taking the light theme's [color tokens](/tokens/color) a To install the dark theme, add the following to the `` section of your page. ```html - + ``` To activate the theme, apply the `sl-theme-dark` class to the `` element. @@ -146,4 +149,4 @@ Shoelace doesn't try to auto-detect the user's light/dark mode preference. This - Allow the user to override the setting in your app - Remember the user's preference and restore it on subsequent logins -Shoelace avoids using the `prefers-color-scheme` media query because not all apps support dark mode, and it would break things for the ones that don't. \ No newline at end of file +Shoelace avoids using the `prefers-color-scheme` media query because not all apps support dark mode, and it would break things for the ones that don't. diff --git a/docs/pages/index.md b/docs/pages/index.md index 1e09273a..f9b62d92 100644 --- a/docs/pages/index.md +++ b/docs/pages/index.md @@ -137,4 +137,4 @@ Special thanks to the following projects and individuals that help make Shoelace - Positioning of dropdowns, tooltips, et al is handled by [Floating UI](https://floating-ui.com/) - Animations are courtesy of [animate.css](https://animate.style/) - Search is powered by [Lunr](https://lunrjs.com/) -- The Shoelace logo was designed with a single shoelace by [Adam K Olson](https://twitter.com/adamkolson) \ No newline at end of file +- The Shoelace logo was designed with a single shoelace by [Adam K Olson](https://twitter.com/adamkolson) From 47018d61cd82b5f6ca3bf532ba92eb9003074a5c Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 12 Jun 2023 15:32:45 -0400 Subject: [PATCH 07/15] don't bundle anything for npm --- scripts/build.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/build.js b/scripts/build.js index 7daa28fe..41926694 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -72,15 +72,12 @@ async function buildTheDocs(watch = false) { // async function buildTheSource() { const alwaysExternal = ['@lit-labs/react', 'react']; - const packageJSON = await fs.readFile('./package.json'); const dependencies = [ ...Object.keys(packageJSON.dependencies || {}), ...Object.keys(packageJSON.peerDependencies || {}) ]; - const allExternal = [...alwaysExternal, ...dependencies]; - const cdnConfig = { format: 'esm', target: 'es2017', @@ -124,7 +121,7 @@ async function buildTheSource() { const npmConfig = { ...cdnConfig, - external: allExternal, + bundle: false, outdir }; From c4c2e8e3a97c6298ab0598fb60d9e545e110c2a4 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 12 Jun 2023 15:36:35 -0400 Subject: [PATCH 08/15] make esbuild happy again --- scripts/build.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build.js b/scripts/build.js index 41926694..9cfe2a58 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -122,6 +122,7 @@ async function buildTheSource() { const npmConfig = { ...cdnConfig, bundle: false, + external: undefined, outdir }; From 65b72217ea42ad56943c088a3bd5d70c5168dff1 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 12 Jun 2023 16:15:29 -0400 Subject: [PATCH 09/15] remove copydir and fix virtual path for serve --- scripts/build.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/build.js b/scripts/build.js index 9cfe2a58..75e9b240 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -11,10 +11,7 @@ import getPort, { portNumbers } from 'get-port'; import ora from 'ora'; import util from 'util'; -const { copydir, serve } = commandLineArgs([ - { name: 'copydir', type: String }, - { name: 'serve', type: Boolean } -]); +const { serve } = commandLineArgs([{ name: 'serve', type: Boolean }]); const outdir = 'dist'; const cdndir = 'cdn'; const sitedir = '_site'; @@ -205,7 +202,7 @@ await nextTask('Building source files', async () => { buildResults = await buildTheSource(); }); -// Copy the build output to the documentation dist directory +// Copy the CDN build to the docs await nextTask(`Copying the build to "${sitedir}"`, async () => { await deleteAsync(sitedir); @@ -238,7 +235,7 @@ if (serve) { server: { baseDir: sitedir, routes: { - '/dist': './dist' + '/cdn': './cdn' } } }; From b0b6ea943ea0e3f7957dffa0e7551284ad1fc95b Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 12 Jun 2023 16:15:52 -0400 Subject: [PATCH 10/15] use cdn bundle for docs --- docs/_includes/default.njk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_includes/default.njk b/docs/_includes/default.njk index a7b7e8b2..2a29169d 100644 --- a/docs/_includes/default.njk +++ b/docs/_includes/default.njk @@ -34,9 +34,9 @@ {# Shoelace #} - - - + + + {# Set the initial theme and menu states here to prevent flashing #} + + ``` @@ -50,11 +45,9 @@ The traditional CDN loader registers all Shoelace elements up front. Note that, The code above will load the light theme. If you want to use the [dark theme](/getting-started/themes#dark-theme) instead, update the stylesheet as shown below and add `` to your page. + ```html - + ``` ### Light & Dark Theme @@ -77,9 +70,9 @@ If you want to load the light or dark theme based on the user's `prefers-color-s Now you can [start using Shoelace!](/getting-started/usage) -## NPM installation +## npm installation -If you don't want to use the CDN, you can install Shoelace from NPM with the following command. +If you don't want to use the CDN, you can install Shoelace from npm with the following command. ```bash npm install @shoelace-style/shoelace @@ -130,7 +123,7 @@ Shoelace also exports a `getBasePath()` method you can use to reference assets. ## Cherry Picking -Cherry picking can be done from [the CDN](#cdn-installation-easiest) or from [NPM](#npm-installation). This approach will load only the components you need up front, while limiting the number of files the browser has to download. The disadvantage is that you need to import each individual component. +Cherry picking can be done from [the CDN](#cdn-installation-easiest) or from [npm](#npm-installation). This approach will load only the components you need up front, while limiting the number of files the browser has to download. The disadvantage is that you need to import each individual component. Here's an example that loads only the button component. Again, if you're not using a module resolver, you'll need to adjust the path to point to the folder Shoelace is in. @@ -189,18 +182,13 @@ setBasePath('/path/to/shoelace/%NPMDIR% Component modules include side effects for registration purposes. Because of this, importing directly from `@shoelace-style/shoelace` may result in a larger bundle size than necessary. For optimal tree shaking, always cherry pick, i.e. import components and utilities from their respective files, as shown above. ::: -## The difference between CDN and NPM +## The difference between CDN and npm -You'll notice above that the CDN links all start with `/%CDNDIR%/` and imports using NPM use `/%NPMDIR%/`. -The `/%CDNDIR%` files use a different bundle from `/%NPMDIR%`. `/%CDNDIR%` files come "pre-bundled" which means all dependencies are -inlined so you do not need to worry about loading any additional libraries. `/%NPMDIR%` does **NOT** pre-bundle dependencies -allowing for your bundler of choice to more efficiently deduplicate dependencies resulting in smaller overall bundles -and greater code sharing. +You'll notice that the CDN links all start with `/%CDNDIR%/` and npm imports use `/%NPMDIR%/`. The `/%CDNDIR%` files are bundled separately from the `/%NPMDIR%` files. The `/%CDNDIR%` files come pre-bundled, which means all dependencies are inlined so you do not need to worry about loading additional libraries. The `/%NPMDIR%` files **DO NOT** come pre-bundled, allowing your bundler of choice to more efficiently deduplicate dependencies, resulting in smaller bundles and optimal code sharing. -TLDR: +TL;DR: -- `@shoelace-style/shoelace/%CDNDIR%` is for CDN -- `@shoelace-style/shoelace/%NPMDIR%` is for NPM +- `@shoelace-style/shoelace/%CDNDIR%` is for CDN users +- `@shoelace-style/shoelace/%NPMDIR%` is for npm users -This change was introduced in `v2.5.0` to address issues around installations from NPM -loading multiple versions of libraries such as the Lit web component library which Shoelace uses internally. +This change was introduced in `v2.5.0` to address issues around installations from npm loading multiple versions of libraries (such as the Lit) that Shoelace uses internally. From 834d44e0e471827933ff5b1dc45b86d0184514ac Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 12 Jun 2023 16:22:20 -0400 Subject: [PATCH 12/15] npm --- cspell.json | 1 - scripts/make-icons.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cspell.json b/cspell.json index e9be0135..7c19f825 100644 --- a/cspell.json +++ b/cspell.json @@ -148,7 +148,6 @@ "textareas", "textfield", "tinycolor", - "TLDR", "transitionend", "treeitem", "Triaging", diff --git a/scripts/make-icons.js b/scripts/make-icons.js index f43dc41a..e7312c4b 100644 --- a/scripts/make-icons.js +++ b/scripts/make-icons.js @@ -23,7 +23,7 @@ const url = `https://github.com/twbs/icons/archive/v${version}.zip`; try { await fs.stat(`${srcPath}/LICENSE.md`); } catch { - // Download the source from GitHub (since not everything is published to NPM) + // Download the source from GitHub (since not everything is published to npm) await download(url, './.cache/icons', { extract: true }); } From a5f1bc6c82f17acc64f837a1cb19ab98d6070f5b Mon Sep 17 00:00:00 2001 From: konnorrogers Date: Mon, 12 Jun 2023 16:23:47 -0400 Subject: [PATCH 13/15] fix circular dependency --- src/translations/en.ts | 2 +- src/utilities/localize.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/translations/en.ts b/src/translations/en.ts index 0a52fa9e..d242bca5 100644 --- a/src/translations/en.ts +++ b/src/translations/en.ts @@ -1,4 +1,4 @@ -import { registerTranslation } from '../utilities/localize'; +import { registerTranslation } from '@shoelace-style/localize'; import type { Translation } from '../utilities/localize'; const translation: Translation = { diff --git a/src/utilities/localize.ts b/src/utilities/localize.ts index e3298e6b..0b52443a 100644 --- a/src/utilities/localize.ts +++ b/src/utilities/localize.ts @@ -1,4 +1,4 @@ -import '../translations/en'; +import '../translations/en.js'; import { LocalizeController as DefaultLocalizationController } from '@shoelace-style/localize'; // Register English as the default/fallback language import type { Translation as DefaultTranslation } from '@shoelace-style/localize'; From 15474b83b1234ab5a86593bb394a075cb452aa2e Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 12 Jun 2023 16:24:21 -0400 Subject: [PATCH 14/15] update --- docs/pages/resources/changelog.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md index 728b743b..573e637f 100644 --- a/docs/pages/resources/changelog.md +++ b/docs/pages/resources/changelog.md @@ -14,7 +14,16 @@ New versions of Shoelace are released as-needed and generally occur when a criti ## Next -- Added a `cdn/` path for bundled dependencies. Imports for NPM users will remain the same. [#1369](https://github.com/shoelace-style/shoelace/pull/1369) +This release [unbundles Lit](https://github.com/shoelace-style/shoelace/issues/559) (and other dependencies) from Shoelace. There are now two distributions for the project: + +1. `cdn/` – a bundled, CDN-ready distribution +2. `dist/` – an unbundled, npm-ready distribution + +:::warning +If you're a CDN user, you must update your path to point to `cdn/` instead of `dist/`. You can copy and paste the latest paths from the [installation page](/getting-started/installation). +::: + +- Added a `cdn/` distribution for bundled dependencies (imports for npm users remain the same) [#1369](https://github.com/shoelace-style/shoelace/pull/1369) - Added the `checkbox` part and related exported parts to `` so you can target it with CSS [#1318](https://github.com/shoelace-style/shoelace/discussions/1318) - Added the `submenu-icon` part to `` (submenus have not been implemented yet, but this part is required to allow customizations) - Added tests for `` [#1343](https://github.com/shoelace-style/shoelace/pull/1343) From 5ba2c7eeec7b6b0742683cbe0de362691f2be178 Mon Sep 17 00:00:00 2001 From: konnorrogers Date: Tue, 13 Jun 2023 09:31:02 -0400 Subject: [PATCH 15/15] watch cdn, not dist --- docs/eleventy.config.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/eleventy.config.cjs b/docs/eleventy.config.cjs index 228bee49..e0e75221 100644 --- a/docs/eleventy.config.cjs +++ b/docs/eleventy.config.cjs @@ -218,7 +218,7 @@ module.exports = function (eleventyConfig) { eleventyConfig.setServerOptions({ domDiff: false, // disable dom diffing so custom elements don't break on reload, port: 4000, // if port 4000 is taken, 11ty will use the next one available - watch: ['dist/**/*'] // additional files to watch that will trigger server updates (array of paths or globs) + watch: ['cdn/**/*'] // additional files to watch that will trigger server updates (array of paths or globs) }); //