Compare commits
2 Commits
data-actio
...
kj/renamin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed10f36b28 | ||
|
|
a13be817db |
@@ -4,13 +4,11 @@
|
||||
name: Client Tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [next]
|
||||
pull_request:
|
||||
branches: [next]
|
||||
|
||||
|
||||
jobs:
|
||||
client_test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -32,17 +30,10 @@ jobs:
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
run: npm run prettier
|
||||
working-directory: ./packages/webawesome
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
working-directory: ./packages/webawesome
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
working-directory: ./packages/webawesome
|
||||
|
||||
- name: Run CSR tests
|
||||
# FAIL_FAST to fail on first failing test.
|
||||
run: FAIL_FAST="true" CSR_ONLY="true" npm run test
|
||||
working-directory: ./packages/webawesome
|
||||
@@ -1,12 +1,11 @@
|
||||
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
# # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: SSR Tests
|
||||
|
||||
on:
|
||||
# push:
|
||||
# branches: [next]
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [next]
|
||||
|
||||
jobs:
|
||||
ssr_test:
|
||||
@@ -26,17 +25,17 @@ jobs:
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
# Just lint here too. Save some GH Action minutes and not need to use "depends_on" or anything.
|
||||
- name: Lint
|
||||
run: npm run prettier
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
working-directory: ./packages/webawesome
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
working-directory: ./packages/webawesome
|
||||
|
||||
- name: Run SSR tests
|
||||
# FAIL_FAST to fail on first failing test.
|
||||
run: FAIL_FAST="true" SSR_ONLY="true" npm run test
|
||||
working-directory: ./packages/webawesome
|
||||
|
||||
10
.gitignore
vendored
@@ -1,12 +1,12 @@
|
||||
_site
|
||||
.cache
|
||||
.DS_Store
|
||||
package.json
|
||||
package-lock.json
|
||||
dist/
|
||||
dist-cdn/
|
||||
docs/public/pagefind
|
||||
node_modules
|
||||
packages/**/*/src/react
|
||||
src/react
|
||||
.astro
|
||||
cdn/
|
||||
yarn.lock
|
||||
_bundle_
|
||||
/packages/webawesome-pro
|
||||
/packages/webawesome-app
|
||||
|
||||
@@ -1,23 +1,15 @@
|
||||
# Files are relative to .prettierignore at the root of this monorepo.
|
||||
# <https://github.com/prettier/prettier-vscode/issues/1252>
|
||||
|
||||
*.hbs
|
||||
*.md
|
||||
!packages/webawesome/docs/docs/patterns/**/*.md
|
||||
docs/docs/patterns/blog-news/post-list.md
|
||||
**/*/.cache
|
||||
.cache
|
||||
.github
|
||||
cspell.json
|
||||
packages/**/*/dist
|
||||
packages/**/*/dist-cdn
|
||||
packages/**/*/docs/search.json
|
||||
packages/**/*/src/components/icon/icons
|
||||
packages/**/*/src/react/index.ts
|
||||
**/*/package.json
|
||||
**/*/package-lock.json
|
||||
**/*/tsconfig.json
|
||||
**/*/tsconfig.prod.json
|
||||
dist
|
||||
docs/search.json
|
||||
src/components/icon/icons
|
||||
src/react/index.ts
|
||||
node_modules
|
||||
|
||||
packages/**/*/_site
|
||||
packages/webawesome/docs/assets/scripts/prism-downloaded.js
|
||||
package.json
|
||||
package-lock.json
|
||||
tsconfig.json
|
||||
cdn
|
||||
_site
|
||||
|
||||
41
README.md
@@ -31,30 +31,6 @@ If that's not what you're trying to do, the [documentation website](https://weba
|
||||
|
||||
Components are built with [LitElement](https://lit-element.polymer-project.org/), a custom elements base class that provides an intuitive API and reactive data binding. The build is a custom script with bundling powered by [esbuild](https://esbuild.github.io/).
|
||||
|
||||
### Understanding the Web Awesome monorepo
|
||||
|
||||
Web Awesome uses [NPM workspaces](https://docs.npmjs.com/cli/v11/using-npm/workspaces) for its monorepo structure and is fairly minimal in what it provides.
|
||||
|
||||
By using a NPM workspaces and a monorepo structure, we can get consistent builds, shared configurations, and reduced duplication across repositories which reduces regressions and forces consistency across `webawesome`, `webawesome-pro`, and `webawesome-app`.
|
||||
|
||||
Generally, if you plan to only work with the free version of `webawesome` it is easiest to go to `packages/webawesome` and run all commands from there.
|
||||
|
||||
### Where do NPM dependencies go?
|
||||
|
||||
Any dependencies intended to be used across all packages (IE: `prettier`, `eslint`) that are _NOT_ used at runtime should be in the root `devDependencies` of `package.json`.
|
||||
|
||||
```bash
|
||||
npm install -D -w prettier
|
||||
```
|
||||
|
||||
Any dependencies that will be used at runtime by a package should be part of the specific package's `"dependencies"` such as `lit`. This is required because if that dependency is not in the `packages/*/package.json`, it will not be installed when used via NPM.
|
||||
|
||||
Individual packages are also free to install devDependencies as needed as long as they are specific to that package only.
|
||||
|
||||
To do install a package specific to a package, change your working directory to that package's root
|
||||
|
||||
IE: `cd packages/webawesome && npm install <package-name>`
|
||||
|
||||
### Forking the Repo
|
||||
|
||||
Start by [forking the repo](https://github.com/shoelace-style/webawesome/fork) on GitHub, then clone it locally and install dependencies.
|
||||
@@ -67,10 +43,9 @@ npm install
|
||||
|
||||
### Developing
|
||||
|
||||
Once you've cloned the repo, run the following command from the respective directory within `packages/*`
|
||||
Once you've cloned the repo, run the following command.
|
||||
|
||||
```bash
|
||||
cd packages/webawesome
|
||||
npm start
|
||||
```
|
||||
|
||||
@@ -81,35 +56,23 @@ This will spin up the dev server. After the initial build, a browser will open a
|
||||
To generate a production build, run the following command.
|
||||
|
||||
```bash
|
||||
cd packages/webawesome
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can also run `npm run build:serve` to start an [`http-server`](https://www.npmjs.com/package/http-server) instance on `http://localhost:4000` after the build completes, so you can preview the production build.
|
||||
|
||||
### Creating New Components
|
||||
|
||||
To scaffold a new component, run the following command, replacing `wa-tag-name` with the desired tag name.
|
||||
|
||||
```bash
|
||||
cd packages/webawesome
|
||||
npm run create wa-tag-name
|
||||
```
|
||||
|
||||
This will generate a source file, a stylesheet, and a docs page for you. When you start the dev server, you'll find the new component in the "Components" section of the sidebar.
|
||||
|
||||
### Adding additional packages
|
||||
|
||||
Right now the only additional packages are in private repositories.
|
||||
|
||||
To add additional packages from other repositories, run: `git clone <url> packages/<package-name>` to clone your repo into `packages/`.
|
||||
|
||||
Make sure to run `npm install` at the root of the monorepo after adding your package!
|
||||
|
||||
### Contributing
|
||||
|
||||
Web Awesome is an open source project and contributions are encouraged! If you're interesting in contributing, please review the [contribution guidelines](CONTRIBUTING.md) first.
|
||||
|
||||
## License
|
||||
|
||||
Web Awesome is available under the terms of the MIT license.
|
||||
Web Awesome is available under the terms of the MIT license.
|
||||
|
||||
@@ -15,19 +15,16 @@
|
||||
"autoloading",
|
||||
"autoplay",
|
||||
"bezier",
|
||||
"Blockquotes",
|
||||
"boxicons",
|
||||
"CACHEABLE",
|
||||
"callout",
|
||||
"callouts",
|
||||
"canvastext",
|
||||
"chatbubble",
|
||||
"checkmark",
|
||||
"Clippy",
|
||||
"codebases",
|
||||
"codepen",
|
||||
"colocated",
|
||||
"colorjs",
|
||||
"colour",
|
||||
"combobox",
|
||||
"Commonmark",
|
||||
@@ -61,8 +58,6 @@
|
||||
"exportmaps",
|
||||
"exportparts",
|
||||
"fieldsets",
|
||||
"focusin",
|
||||
"focusout",
|
||||
"fontawesome",
|
||||
"formaction",
|
||||
"formdata",
|
||||
@@ -72,7 +67,6 @@
|
||||
"formtarget",
|
||||
"FOUC",
|
||||
"FOUCE",
|
||||
"Frontmatter",
|
||||
"fullscreen",
|
||||
"gestern",
|
||||
"giga",
|
||||
@@ -134,7 +128,6 @@
|
||||
"petabit",
|
||||
"Preact",
|
||||
"preconnect",
|
||||
"prerendered",
|
||||
"prismjs",
|
||||
"progressbar",
|
||||
"radiogroup",
|
||||
@@ -155,7 +148,6 @@
|
||||
"scrollbars",
|
||||
"scrollend",
|
||||
"scroller",
|
||||
"Scrollers",
|
||||
"Segoe",
|
||||
"semibold",
|
||||
"shadowrootmode",
|
||||
|
||||
@@ -3,12 +3,9 @@ import { customElementVsCodePlugin } from 'custom-element-vs-code-integration';
|
||||
// import { customElementVuejsPlugin } from 'custom-element-vuejs-integration';
|
||||
import { parse } from 'comment-parser';
|
||||
import fs from 'fs';
|
||||
import * as path from 'node:path';
|
||||
import { pascalCase } from 'pascal-case';
|
||||
import * as url from 'url';
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
const packageData = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
||||
const packageData = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
const { name, description, version, author, homepage, license } = packageData;
|
||||
const outdir = 'dist-cdn';
|
||||
|
||||
165
docs/.eleventy.js
Normal file
@@ -0,0 +1,165 @@
|
||||
import { anchorHeadingsPlugin } from './_utils/anchor-headings.js';
|
||||
import { codeExamplesPlugin } from './_utils/code-examples.js';
|
||||
import { copyCodePlugin } from './_utils/copy-code.js';
|
||||
import { currentLink } from './_utils/current-link.js';
|
||||
import { highlightCodePlugin } from './_utils/highlight-code.js';
|
||||
import { markdown } from './_utils/markdown.js';
|
||||
import { removeDataAlphaElements } from './_utils/remove-data-alpha-elements.js';
|
||||
// import { formatCodePlugin } from './_utils/format-code.js';
|
||||
import litPlugin from '@lit-labs/eleventy-plugin-lit';
|
||||
import { readFile } from 'fs/promises';
|
||||
import componentList from './_data/componentList.js';
|
||||
import * as filters from './_utils/filters.js';
|
||||
import { outlinePlugin } from './_utils/outline.js';
|
||||
import { replaceTextPlugin } from './_utils/replace-text.js';
|
||||
import { searchPlugin } from './_utils/search.js';
|
||||
|
||||
import process from 'process';
|
||||
|
||||
const packageData = JSON.parse(await readFile('./package.json', 'utf-8'));
|
||||
const isAlpha = process.argv.includes('--alpha');
|
||||
const isDev = process.argv.includes('--develop');
|
||||
|
||||
export default function (eleventyConfig) {
|
||||
// NOTE - alpha setting removes certain pages
|
||||
if (isAlpha) {
|
||||
eleventyConfig.ignores.add('**/experimental/**');
|
||||
eleventyConfig.ignores.add('**/layout/**');
|
||||
eleventyConfig.ignores.add('**/patterns/**');
|
||||
eleventyConfig.ignores.add('**/style-utilities/**');
|
||||
eleventyConfig.ignores.add('**/components/code-demo.md');
|
||||
eleventyConfig.ignores.add('**/components/viewport-demo.md');
|
||||
}
|
||||
|
||||
// Add template data
|
||||
eleventyConfig.addGlobalData('package', packageData);
|
||||
eleventyConfig.addGlobalData('isAlpha', isAlpha);
|
||||
|
||||
// Template filters - {{ content | filter }}
|
||||
eleventyConfig.addFilter('inlineMarkdown', content => markdown.renderInline(content || ''));
|
||||
eleventyConfig.addFilter('markdown', content => markdown.render(content || ''));
|
||||
|
||||
for (let name in filters) {
|
||||
eleventyConfig.addFilter(name, filters[name]);
|
||||
}
|
||||
|
||||
eleventyConfig.addFilter('sort', (arr, key = 'data.title') => {
|
||||
key = key.split('.');
|
||||
return arr.sort((a, b) => {
|
||||
let aVal = key.reduce((obj, i) => obj?.[i], a);
|
||||
let bVal = key.reduce((obj, i) => obj?.[i], b);
|
||||
return aVal.localeCompare(bVal);
|
||||
});
|
||||
});
|
||||
|
||||
// Shortcodes - {% shortCode arg1, arg2 %}
|
||||
eleventyConfig.addShortcode('cdnUrl', location => {
|
||||
return `https://early.webawesome.com/webawesome@${packageData.version}/dist/` + location.replace(/^\//, '');
|
||||
});
|
||||
|
||||
// Helpers
|
||||
|
||||
// Remove elements that have [data-alpha="remove"]
|
||||
eleventyConfig.addPlugin(removeDataAlphaElements({ isAlpha }));
|
||||
|
||||
// Use our own markdown instance
|
||||
eleventyConfig.setLibrary('md', markdown);
|
||||
|
||||
// Add anchors to headings
|
||||
eleventyConfig.addPlugin(anchorHeadingsPlugin({ container: '#content' }));
|
||||
|
||||
// Add an outline to the page
|
||||
eleventyConfig.addPlugin(
|
||||
outlinePlugin({
|
||||
container: '#content',
|
||||
target: '.outline-links',
|
||||
selector: 'h2, h3',
|
||||
ifEmpty: doc => {
|
||||
doc.querySelector('#outline')?.remove();
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// Add current link classes
|
||||
eleventyConfig.addPlugin(currentLink());
|
||||
|
||||
// Add code examples for `<code class="example">` blocks
|
||||
eleventyConfig.addPlugin(codeExamplesPlugin);
|
||||
|
||||
// Highlight code blocks with Prism
|
||||
eleventyConfig.addPlugin(highlightCodePlugin());
|
||||
|
||||
// Add copy code buttons to code blocks
|
||||
eleventyConfig.addPlugin(copyCodePlugin());
|
||||
|
||||
// Various text replacements
|
||||
eleventyConfig.addPlugin(
|
||||
replaceTextPlugin([
|
||||
// Replace [issue:1234] with a link to the issue on GitHub
|
||||
{
|
||||
replace: /\[pr:([0-9]+)\]/gs,
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/pull/$1">#$1</a>',
|
||||
},
|
||||
// Replace [pr:1234] with a link to the pull request on GitHub
|
||||
{
|
||||
replace: /\[issue:([0-9]+)\]/gs,
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/issues/$1">#$1</a>',
|
||||
},
|
||||
// Replace [discuss:1234] with a link to the discussion on GitHub
|
||||
{
|
||||
replace: /\[discuss:([0-9]+)\]/gs,
|
||||
replaceWith: '<a href="https://github.com/shoelace-style/webawesome/discussions/$1">#$1</a>',
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
// SSR plugin
|
||||
if (!isDev) {
|
||||
//
|
||||
// Problematic components in SSR land:
|
||||
// - animation (breaks on navigation + ssr with Turbo)
|
||||
// - mutation-observer (why SSR this?)
|
||||
// - resize-observer (why SSR this?)
|
||||
// - tooltip (why SSR this?)
|
||||
//
|
||||
const omittedModules = [];
|
||||
const componentModules = componentList
|
||||
.filter(component => !omittedModules.includes(component.tagName.split(/wa-/)[1]))
|
||||
.map(component => {
|
||||
const name = component.tagName.split(/wa-/)[1];
|
||||
return `./dist/components/${name}/${name}.js`;
|
||||
});
|
||||
|
||||
eleventyConfig.addPlugin(litPlugin, {
|
||||
mode: 'worker',
|
||||
componentModules,
|
||||
});
|
||||
}
|
||||
|
||||
// Build the search index
|
||||
eleventyConfig.addPlugin(
|
||||
searchPlugin({
|
||||
filename: '',
|
||||
selectorsToIgnore: ['code.example'],
|
||||
getContent: doc => doc.querySelector('#content')?.textContent ?? '',
|
||||
}),
|
||||
);
|
||||
|
||||
// Production-only plugins
|
||||
//
|
||||
// TODO - disabled because it takes about a minute to run now
|
||||
//
|
||||
// if (!isDev) {
|
||||
// // Run Prettier on each file (prod only because it can be slow)
|
||||
// eleventyConfig.addPlugin(formatCodePlugin());
|
||||
// }
|
||||
|
||||
return {
|
||||
markdownTemplateEngine: 'njk',
|
||||
dir: {
|
||||
includes: '_includes',
|
||||
layouts: '_layouts',
|
||||
},
|
||||
templateFormats: ['njk', 'md'],
|
||||
};
|
||||
}
|
||||
@@ -2,15 +2,12 @@
|
||||
* @module components Fetches components from custom-elements.json and exposes them in a saner format.
|
||||
*/
|
||||
import { readFileSync } from 'fs';
|
||||
import { dirname, join, resolve } from 'path';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const customElementsJSON = process.env.DIST_DIR
|
||||
? join(process.env.DIST_DIR, 'custom-elements.json')
|
||||
: resolve(__dirname, '../../dist/custom-elements.json');
|
||||
|
||||
const manifest = JSON.parse(readFileSync(customElementsJSON), 'utf-8');
|
||||
const manifest = JSON.parse(readFileSync(resolve(__dirname, '../../dist/custom-elements.json'), 'utf-8'));
|
||||
|
||||
const components = manifest.modules.flatMap(module => {
|
||||
return module.declarations
|
||||
43
docs/_data/componentsBy.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import components from './components.js';
|
||||
|
||||
const by = {
|
||||
attribute: {},
|
||||
slot: {},
|
||||
event: {},
|
||||
method: {},
|
||||
cssPart: {},
|
||||
cssProperty: {},
|
||||
};
|
||||
|
||||
function getAll(component, type) {
|
||||
let prop = type + 's';
|
||||
if (type === 'cssProperty') {
|
||||
prop = 'cssProperties';
|
||||
}
|
||||
|
||||
return component[prop] ?? [];
|
||||
}
|
||||
|
||||
for (const componentName in components) {
|
||||
const component = components[componentName];
|
||||
|
||||
for (const type of ['attribute', 'slot', 'event', 'method', 'cssPart', 'cssProperty']) {
|
||||
for (const item of getAll(component, type)) {
|
||||
by[type][item.name] ??= [];
|
||||
by[type][item.name].push(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by descending number of components
|
||||
const sortByLengthDesc = (a, b) => b[1].length - a[1].length;
|
||||
|
||||
for (const key in by) {
|
||||
by[key] = sortObject(by[key], sortByLengthDesc);
|
||||
}
|
||||
|
||||
export default by;
|
||||
|
||||
function sortObject(obj, sorter) {
|
||||
return Object.fromEntries(Object.entries(obj).sort(sorter));
|
||||
}
|
||||
98
docs/_includes/base-wide.njk
Normal file
178
docs/_includes/base.njk
Normal file
@@ -0,0 +1,178 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-fa-kit-code="b10bfbde90" data-cdn-url="{% cdnUrl %}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="{{ description }}">
|
||||
<meta name="theme-color" content="#f36944">
|
||||
{% if noindex %}<meta name="robots" content="noindex">{% endif %}
|
||||
|
||||
<title>{{ title }}</title>
|
||||
|
||||
<link rel="icon" href="/assets/images/webawesome-logo.svg" />
|
||||
<link rel="apple-touch-icon" href="/assets/images/app-icon.png">
|
||||
|
||||
{# Scripts #}
|
||||
{# Hydration stuff #}
|
||||
<script src="/assets/scripts/hydration-errors.js"></script>
|
||||
<link rel="stylesheet" href="/assets/styles/hydration-errors.css">
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.10/+esm"></script>
|
||||
|
||||
<script type="module" src="/assets/scripts/code-examples.js"></script>
|
||||
<script type="module" src="/assets/scripts/color-scheme.js"></script>
|
||||
<script type="module" src="/assets/scripts/copy-code.js"></script>
|
||||
<script type="module" src="/assets/scripts/preset-theme.js"></script>
|
||||
<script type="module" src="/assets/scripts/scroll.js"></script>
|
||||
<script type="module" src="/assets/scripts/turbo.js"></script>
|
||||
<script type="module" src="/assets/scripts/search.js"></script>
|
||||
<script type="module" src="/assets/scripts/outline.js"></script>
|
||||
<script defer data-domain="backers.webawesome.com" src="https://plausible.io/js/script.js"></script>
|
||||
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="/dist/styles/themes/default.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/applied.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/utilities.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css" />
|
||||
|
||||
{# Docs styles #}
|
||||
<link rel="stylesheet" href="/assets/styles/docs.css" />
|
||||
|
||||
{# Set the theme to prevent flashing #}
|
||||
<script>
|
||||
function getColorScheme() {
|
||||
return localStorage.getItem('colorScheme') || 'auto';
|
||||
}
|
||||
|
||||
function getPresetTheme () {
|
||||
return localStorage.getItem('presetTheme') || 'default';
|
||||
}
|
||||
|
||||
function isDark() {
|
||||
const colorScheme = getColorScheme()
|
||||
if (colorScheme === 'auto') {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
}
|
||||
return colorScheme === 'dark';
|
||||
}
|
||||
|
||||
const oldStylesheet = document.querySelector("#theme-stylesheet")
|
||||
|
||||
const newStylesheet = document.createElement("link")
|
||||
|
||||
let preset = getPresetTheme()
|
||||
newStylesheet.href = `/dist/styles/themes/${preset}.css`
|
||||
newStylesheet.rel = "preload"
|
||||
newStylesheet.as = "style"
|
||||
|
||||
document.head.append(newStylesheet)
|
||||
|
||||
function updateStylesheet () {
|
||||
newStylesheet.rel = "stylesheet"
|
||||
newStylesheet.id = "theme-stylesheet"
|
||||
requestAnimationFrame(() => oldStylesheet.remove())
|
||||
}
|
||||
|
||||
newStylesheet.addEventListener("load", updateStylesheet)
|
||||
|
||||
document.documentElement.classList.toggle(
|
||||
`wa-theme-${preset}-dark`,
|
||||
isDark()
|
||||
);
|
||||
</script>
|
||||
</head>
|
||||
<body class="layout-{{ layout | stripExtension }}">
|
||||
<!-- use view="desktop" as default to reduce layout jank on desktop site. -->
|
||||
<wa-page view="desktop" disable-navigation-toggle="">
|
||||
<header slot="header">
|
||||
{# Logo #}
|
||||
<div id="docs-branding">
|
||||
{# Nav toggle #}
|
||||
<wa-button appearance="plain" size="small" data-toggle-nav>
|
||||
<wa-icon name="bars" label="Toggle navigation"></wa-icon>
|
||||
</wa-button>
|
||||
|
||||
<a href="/" aria-label="Web Awesome">
|
||||
<span class="only-desktop">{% include "logo.njk" %}</span>
|
||||
<span class="only-mobile">{% include "logo-simple.njk" %}</span>
|
||||
</a>
|
||||
<small id="version-number" class="only-desktop">{{ package.version }}</small>
|
||||
<wa-badge variant="warning" appearance="filled" class="only-desktop">Alpha</wa-badge>
|
||||
</div>
|
||||
|
||||
<div id="docs-toolbar">
|
||||
{# Desktop selectors #}
|
||||
<div class="only-desktop">
|
||||
{% include "preset-theme-selector.njk" %}
|
||||
{% include "color-scheme-selector.njk" %}
|
||||
</div>
|
||||
|
||||
{# Search #}
|
||||
<wa-button id="search-trigger" appearance="outlined" size="small" data-search>
|
||||
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
|
||||
Search
|
||||
<kbd slot="suffix" class="only-desktop">/</kbd>
|
||||
</wa-button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{# Sidebar #}
|
||||
{% if hasSidebar %}
|
||||
{# Mobile selectors #}
|
||||
<div class="only-mobile" slot="navigation-header">
|
||||
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));">
|
||||
{% include "preset-theme-selector.njk" %}
|
||||
{% include "color-scheme-selector.njk" %}
|
||||
</div>
|
||||
</div>
|
||||
<div slot="navigation" id="sidebar" class="docs-aside" data-remember-scroll>
|
||||
{% include "sidebar.njk" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Outline #}
|
||||
{% if hasOutline %}
|
||||
<aside slot="aside" id="outline" class="docs-aside">
|
||||
<nav id="outline-standard" class="outline-links">
|
||||
<h2><a href="#content">{{ title }}</a></h2>
|
||||
</nav>
|
||||
</aside>
|
||||
{% endif %}
|
||||
|
||||
{# Main #}
|
||||
<main id="content">
|
||||
{# Expandable outline #}
|
||||
<nav id="outline-expandable">
|
||||
<details class="outline-links">
|
||||
<summary>On this page</summary>
|
||||
</details>
|
||||
</nav>
|
||||
|
||||
{% set breadcrumbs = page.url | breadcrumbs %}
|
||||
{% if breadcrumbs.length > 0 %}
|
||||
<wa-breadcrumb id="docs-breadcrumbs">
|
||||
{% for crumb in breadcrumbs %}
|
||||
<wa-breadcrumb-item href="{{ crumb.url }}">{{ crumb.title }}</wa-breadcrumb-item>
|
||||
{% endfor %}
|
||||
<wa-breadcrumb-item>{# Current page #}</wa-breadcrumb-item>
|
||||
</wa-breadcrumb>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
|
||||
{% block beforeContent %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
{% block afterContent %}{% endblock %}
|
||||
</main>
|
||||
|
||||
{% include 'search.njk' %}
|
||||
</wa-page>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
15
docs/_includes/color-scheme-selector.njk
Normal file
@@ -0,0 +1,15 @@
|
||||
{# Color scheme selector #}
|
||||
<wa-dropdown id="color-scheme-selector">
|
||||
<wa-button slot="trigger" appearance="filled" size="small" pill caret title="Press \ to toggle">
|
||||
<wa-icon class="only-light" slot="prefix" name="sun" variant="regular"></wa-icon>
|
||||
<wa-icon class="only-dark" slot="prefix" name="moon" variant="regular"></wa-icon>
|
||||
<span class="only-light">Light</span>
|
||||
<span class="only-dark">Dark</span>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item type="checkbox" value="light">Light</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="dark">Dark</wa-menu-item>
|
||||
<wa-divider></wa-divider>
|
||||
<wa-menu-item type="checkbox" value="auto">System</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
|
Before Width: | Height: | Size: 742 B After Width: | Height: | Size: 742 B |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
@@ -1,5 +1,5 @@
|
||||
<div id="page_slots_demo">
|
||||
<link rel="stylesheet" href="/docs/components/page/demo.css">
|
||||
<link rel="stylesheet" href="/assets/examples/page-demo/demo.css">
|
||||
{% set slots = components.page.slots %}
|
||||
|
||||
<fieldset id="page_slots_fieldset">
|
||||
@@ -22,5 +22,5 @@
|
||||
|
||||
<script type="module">
|
||||
const cacheBust = new Date().toString()
|
||||
import(`/docs/components/page/demo.js?${cacheBust}`)
|
||||
import(`/assets/examples/page-demo/demo.js?${cacheBust}`)
|
||||
</script>
|
||||
18
docs/_includes/preset-theme-selector.njk
Normal file
@@ -0,0 +1,18 @@
|
||||
{# Preset theme selector #}
|
||||
<wa-dropdown id="preset-theme-selector">
|
||||
<wa-button slot="trigger" appearance="filled" size="small" pill caret>
|
||||
<wa-icon slot="prefix" name="paintbrush" variant="regular"></wa-icon>
|
||||
<span id="preset-theme-selector__text">Default</span>
|
||||
</wa-button>
|
||||
<wa-menu>
|
||||
<wa-menu-item type="checkbox" value="default">Default</wa-menu-item>
|
||||
<wa-menu-item type="checkbox" value="classic">Classic</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="fa">Font Awesome</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="active">Active</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="brutalist">Brutalism</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="glassy">Glassy</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="migration">Migration</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="playful">Playful</wa-menu-item>
|
||||
<wa-menu-item data-alpha="remove" type="checkbox" value="premium">Premium</wa-menu-item>
|
||||
</wa-menu>
|
||||
</wa-dropdown>
|
||||
@@ -1,4 +1,4 @@
|
||||
<wa-dialog id="site-search" without-header light-dismiss>
|
||||
<wa-dialog id="site-search" no-header light-dismiss>
|
||||
<div id="site-search-container">
|
||||
{# Header #}
|
||||
<header>
|
||||
@@ -8,7 +8,7 @@
|
||||
type="search"
|
||||
appearance="filled"
|
||||
size="large"
|
||||
with-clear
|
||||
clearable
|
||||
placeholder="Search"
|
||||
autofocus
|
||||
autocomplete="off"
|
||||
150
docs/_includes/sidebar.njk
Normal file
@@ -0,0 +1,150 @@
|
||||
{# Getting started #}
|
||||
<h2>Getting Started</h2>
|
||||
<ul>
|
||||
<li><a href="/docs/installation">Installation</a></li>
|
||||
<li><a href="/docs/usage">Usage</a></li>
|
||||
<li><a href="/docs/themes">Themes</a></li>
|
||||
<li><a href="/docs/customizing">Customizing</a></li>
|
||||
<li><a href="/docs/form-controls">Form Controls</a></li>
|
||||
<li><a href="/docs/localization">Localization</a></li>
|
||||
</ul>
|
||||
|
||||
{# Resources #}
|
||||
<h2>Resources</h2>
|
||||
<ul>
|
||||
<li><a href="https://github.com/shoelace-style/webawesome-alpha/discussions" target="_blank">Help & Support</a></li>
|
||||
<li><a href="/docs/resources/community">Community</a></li>
|
||||
<li><a href="/docs/resources/accessibility">Accessibility</a></li>
|
||||
<li><a href="/docs/resources/contributing">Contributing</a></li>
|
||||
<li><a href="/docs/resources/changelog">Changelog</a></li>
|
||||
</ul>
|
||||
|
||||
{# Components #}
|
||||
<wa-details{{ ' open' if '/components/' in page.url }}>
|
||||
<h2 slot=summary>
|
||||
<a href="/docs/components/" title="Overview">Components
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
{% for component in collections.component | sort %}
|
||||
{% if not component.data.parent and not (isAlpha and component.data.isAlpha) %}
|
||||
<li>
|
||||
<a href="/docs/components/{{ component.fileSlug }}">{{ component.data.title }}</a>
|
||||
|
||||
{% if components[component.fileSlug].status == 'experimental' %}<wa-icon name="flask"></wa-icon>{% endif %}
|
||||
{% if component.data.isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
|
||||
<ul>
|
||||
{% for child in collections.component | sort %}
|
||||
{% if child.data.parent == component.fileSlug and not (isAlpha and child.data.isAlpha) %}
|
||||
<li>
|
||||
<a href="/docs/components/{{ child.fileSlug }}">{{ child.data.title }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</wa-details>
|
||||
|
||||
<wa-details{{ ' open' if '/natives/' in page.url }}>
|
||||
<h2 slot=summary>
|
||||
<a href="/docs/natives/" title="Overview">Natives
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
<ul>
|
||||
{% for page in collections.natives | sort %}
|
||||
<li>
|
||||
<a href="/docs/natives/{{ page.fileSlug }}">{{ page.data.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</wa-details>
|
||||
|
||||
{# Layout #}
|
||||
{% if not isAlpha %}
|
||||
<h2>
|
||||
<a href="/docs/layout" title="Overview">Layout
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
<ul>
|
||||
<li><a href="/docs/components/page">Page</a></li>
|
||||
<li><a href="/docs/layout/cluster">Cluster</a></li>
|
||||
<li><a href="/docs/layout/flank">Flank</a></li>
|
||||
<li><a href="/docs/layout/frame">Frame</a></li>
|
||||
<li><a href="/docs/layout/grid">Grid</a></li>
|
||||
<li><a href="/docs/layout/split">Split</a></li>
|
||||
<li><a href="/docs/layout/stack">Stack</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{# Patterns #}
|
||||
{% if not isAlpha %}
|
||||
<h2>Patterns</h2>
|
||||
<ul>
|
||||
<li><a href="/docs/patterns/app">Web App</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce">E-commerce</a>
|
||||
<ul>
|
||||
<li><a href="/docs/patterns/ecommerce-product-review">Product Reviews</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-product-list">Product Lists</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-category-preview">Category Previews</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-shopping-cart">Shopping Carts</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-category-filter">Category Filters</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-product-detail">Product Detail</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-order-summary">Order Summaries</a></li>
|
||||
<li><a href="/docs/patterns/ecommerce-order-history">Order History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="/docs/patterns/blog">Blog</a></li>
|
||||
<li><a href="/docs/patterns/news">News</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{# Theming #}
|
||||
<h2>
|
||||
<a href="/docs/theming" title="Overview">Theming
|
||||
<wa-icon name="grid-2"></wa-icon>
|
||||
</a>
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/docs/theming/color">Color</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/typography">Typography</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/space">Space</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/borders">Borders</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/focus">Focus</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/shadows">Shadows</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/transitions">Transitions</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs/theming/component-groups">Component Groups</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{# Style Utilities #}
|
||||
{% if not isAlpha %}
|
||||
<h2>Style Utilities</h2>
|
||||
<ul>
|
||||
<li><a href="/docs/style-utilities/align-items">Align Items</a></li>
|
||||
<li><a href="/docs/style-utilities/border-radius">Border Radius</a></li>
|
||||
<li><a href="/docs/style-utilities/gap">Gap</a></li>
|
||||
<li><a href="/docs/style-utilities/text">Text</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
Before Width: | Height: | Size: 936 B After Width: | Height: | Size: 936 B |
|
Before Width: | Height: | Size: 380 B After Width: | Height: | Size: 380 B |
|
Before Width: | Height: | Size: 754 B After Width: | Height: | Size: 754 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 742 B After Width: | Height: | Size: 742 B |
|
Before Width: | Height: | Size: 670 B After Width: | Height: | Size: 670 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 420 B After Width: | Height: | Size: 420 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 518 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 524 B After Width: | Height: | Size: 524 B |
|
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 718 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 531 B After Width: | Height: | Size: 531 B |
|
Before Width: | Height: | Size: 300 B After Width: | Height: | Size: 300 B |
|
Before Width: | Height: | Size: 521 B After Width: | Height: | Size: 521 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 614 B After Width: | Height: | Size: 614 B |
|
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 883 B After Width: | Height: | Size: 883 B |
|
Before Width: | Height: | Size: 447 B After Width: | Height: | Size: 447 B |
|
Before Width: | Height: | Size: 388 B After Width: | Height: | Size: 388 B |
|
Before Width: | Height: | Size: 540 B After Width: | Height: | Size: 540 B |
|
Before Width: | Height: | Size: 443 B After Width: | Height: | Size: 443 B |
|
Before Width: | Height: | Size: 547 B After Width: | Height: | Size: 547 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 655 B |
|
Before Width: | Height: | Size: 596 B After Width: | Height: | Size: 596 B |
@@ -2,7 +2,7 @@
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M48.8665 59.1993L33.7329 33H64C63.8352 38.2705 62.3694 43.4244 59.7264 48C57.0833 52.5756 53.3507 56.4213 48.8665 59.1993Z" fill="var(--wa-color-green-70)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M32 64C26.714 64 21.5155 62.6919 16.8665 60.1993L32 34L47.1336 60.1993C42.4845 62.6919 37.286 64 32 64Z" fill="var(--wa-color-blue-60)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.27365 48C1.63063 43.4244 0.164839 38.2706 0 33L30.2671 33L15.1336 59.1993C10.6493 56.4213 6.91666 52.5756 4.27365 48Z" fill="var(--wa-color-indigo-60)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.27365 16C6.91667 11.4244 10.6493 7.57868 15.1336 4.80072L30.2671 31L0 31C0.16484 25.7295 1.63063 20.5756 4.27365 16Z" fill="var(--wa-color-purple-60)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.27365 16C6.91667 11.4244 10.6493 7.57868 15.1336 4.80072L30.2671 31L0 31C0.16484 25.7295 1.63063 20.5756 4.27365 16Z" fill="var(--wa-color-violet-60)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M32 30L16.8665 3.80072C21.5155 1.30813 26.714 0 32 0C37.286 0 42.4845 1.30813 47.1336 3.80072L32 30Z" fill="var(--wa-color-red-60)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.7329 31L48.8665 4.80072C53.3507 7.57868 57.0833 11.4244 59.7264 16C62.3694 20.5756 63.8352 25.7294 64 31L33.7329 31Z" fill="var(--wa-color-yellow-80)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 502 B After Width: | Height: | Size: 502 B |
|
Before Width: | Height: | Size: 790 B After Width: | Height: | Size: 790 B |
|
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 697 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
68
docs/_layouts/blank.njk
Normal file
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-fa-kit-code="b10bfbde90" data-cdn-url="{% cdnUrl %}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="{{ description }}">
|
||||
{% if noindex %}<meta name="robots" content="noindex">{% endif %}
|
||||
|
||||
<title>{{ title }}</title>
|
||||
|
||||
<link rel="icon" href="/assets/images/webawesome-logo.svg" />
|
||||
<link rel="apple-touch-icon" href="/assets/images/app-icon.png">
|
||||
|
||||
{# Scripts #}
|
||||
{# Hydration stuff #}
|
||||
<script src="/assets/scripts/hydration-errors.js"></script>
|
||||
<link rel="stylesheet" href="/assets/styles/hydration-errors.css">
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.10/+esm"></script>
|
||||
|
||||
{# Web Awesome #}
|
||||
<script type="module" src="/dist/webawesome.ssr-loader.js"></script>
|
||||
<link rel="stylesheet" id="theme-stylesheet" />
|
||||
<link rel="stylesheet" href="/dist/styles/applied.css" />
|
||||
<link id="color-stylesheet" rel="stylesheet" href="/dist/styles/utilities.css" />
|
||||
<link rel="stylesheet" href="/dist/styles/forms.css" />
|
||||
|
||||
{# Set the theme to prevent flashing #}
|
||||
<script>
|
||||
function getColorScheme() {
|
||||
return localStorage.getItem('colorScheme') || 'auto';
|
||||
}
|
||||
|
||||
function getPresetTheme () {
|
||||
return localStorage.getItem('presetTheme') || 'default';
|
||||
}
|
||||
|
||||
function isDark() {
|
||||
const colorScheme = getColorScheme()
|
||||
if (colorScheme === 'auto') {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
}
|
||||
return colorScheme === 'dark';
|
||||
}
|
||||
|
||||
const stylesheet = document.getElementById("theme-stylesheet")
|
||||
let preset = getPresetTheme()
|
||||
|
||||
stylesheet.href = `/dist/styles/themes/${preset}.css`
|
||||
|
||||
document.documentElement.classList.toggle(
|
||||
`wa-theme-${preset}-dark`,
|
||||
isDark()
|
||||
);
|
||||
</script>
|
||||
</head>
|
||||
<body class="layout-{{ layout | stripExtension }}">
|
||||
|
||||
{% block beforeContent %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
{% block afterContent %}{% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,41 @@
|
||||
{% extends '../_layouts/block.njk' %}
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
{% set component = components[page.fileSlug] %}
|
||||
{% set description = component.summary %}
|
||||
|
||||
{% extends '../_includes/base.njk' %}
|
||||
|
||||
{# Component header #}
|
||||
{% block beforeContent %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
<div class="component-info">
|
||||
<code class="tag"><{{ component.tagName }}></code>
|
||||
<wa-badge variant="neutral">Since {{ component.since }}</wa-badge>
|
||||
<wa-badge
|
||||
{% if component.status == 'stable' %}variant="brand"{% endif %}
|
||||
{% if component.status == 'experimental' %}variant="warning"{% endif %}
|
||||
>
|
||||
{{ component.status }}
|
||||
</wa-badge>
|
||||
|
||||
{% if isPro %}<wa-badge class="pro">PRO</wa-badge>{% endif %}
|
||||
</div>
|
||||
<p class="summary">
|
||||
{{ component.summary | inlineMarkdown | safe }}
|
||||
</p>
|
||||
{% if natives %}
|
||||
<wa-callout variant="success">
|
||||
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
|
||||
Just want the styles?
|
||||
Check out <a href="/docs/natives/{{ natives }}/">{{ ('/docs/natives/' + natives + '/') | getTitleFromUrl }} natives</a>!
|
||||
</wa-callout>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{# Content #}
|
||||
{% block content %}
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
{# Component API #}
|
||||
{% block afterContent %}
|
||||
@@ -8,7 +44,7 @@
|
||||
<h2>Slots</h2>
|
||||
<p>Learn more about <a href="/docs/usage/#slots">using slots</a>.</p>
|
||||
|
||||
<wa-scroller>
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -31,7 +67,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-scroller>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Properties #}
|
||||
@@ -39,13 +75,13 @@
|
||||
<h2>Attributes & Properties</h2>
|
||||
<p>Learn more about <a href="/docs/usage/#attributes-and-properties">attributes and properties</a>.</p>
|
||||
|
||||
<wa-scroller>
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="table-name">Name</th>
|
||||
<th class="table-description">Description</th>
|
||||
<th class="table-reflect">Reflects</th>
|
||||
<th class="table-reflects">Reflects</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -66,7 +102,7 @@
|
||||
<div><small><strong>Default</strong> <code>{{ prop.default | inlineMarkdown | safe }}</code></small></div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="table-reflect">
|
||||
<td class="table-checkmark">
|
||||
{% if prop.reflects %}
|
||||
<wa-icon name="check"></wa-icon>
|
||||
{% endif %}
|
||||
@@ -78,7 +114,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-scroller>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Methods #}
|
||||
@@ -86,7 +122,7 @@
|
||||
<h2>Methods</h2>
|
||||
<p>Learn more about <a href="/docs/usage/#methods">methods</a>.</p>
|
||||
|
||||
<wa-scroller>
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -113,7 +149,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-scroller>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Events #}
|
||||
@@ -121,7 +157,7 @@
|
||||
<h2>Events</h2>
|
||||
<p>Learn more about <a href="/docs/usage/#events">events</a>.</p>
|
||||
|
||||
<wa-scroller>
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -140,7 +176,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-scroller>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Custom Properties #}
|
||||
@@ -148,7 +184,7 @@
|
||||
<h2>CSS custom properties</h2>
|
||||
<p>Learn more about <a href="/docs/customizing/#custom-properties">CSS custom properties</a>.</p>
|
||||
|
||||
<wa-scroller>
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -172,7 +208,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-scroller>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Custom States #}
|
||||
@@ -180,7 +216,7 @@
|
||||
<h2>Custom States</h2>
|
||||
<p>Learn more about <a href="/docs/customizing/#custom-states">custom states</a>.</p>
|
||||
|
||||
<wa-scroller>
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -199,7 +235,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-scroller>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# CSS Parts #}
|
||||
@@ -207,7 +243,7 @@
|
||||
<h2>CSS parts</h2>
|
||||
<p>Learn more about <a href="/docs/customizing/#css-parts">CSS parts</a>.</p>
|
||||
|
||||
<wa-scroller>
|
||||
<div class="table-scroll">
|
||||
<table class="component-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -224,7 +260,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</wa-scroller>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Dependencies #}
|
||||
@@ -244,7 +280,7 @@
|
||||
{# Importing #}
|
||||
<h2>Importing</h2>
|
||||
<p>
|
||||
The <a href="/docs/#quick-start-autoloading-via-cdn">autoloader</a> is the recommended way to import components. If you prefer to do it manually, use one of the following code snippets.
|
||||
The <a href="/docs/#autoloading">autoloader</a> is the recommended way to import components. If you prefer to do it manually, use one of the following code snippets.
|
||||
</p>
|
||||
|
||||
<wa-tab-group label="How would you like to import this component?">
|
||||
@@ -270,18 +306,4 @@
|
||||
#}
|
||||
</wa-tab-panel>
|
||||
</wa-tab-group>
|
||||
|
||||
<wa-divider></wa-divider>
|
||||
|
||||
<div class="component-help">
|
||||
<strong>Need a hand?</strong>
|
||||
<wa-button size="small" appearance="filled" variant="neutral" href="https://github.com/shoelace-style/webawesome-alpha/issues" target="_blank">
|
||||
<wa-icon slot="prefix" name="bug"></wa-icon>
|
||||
Report a bug
|
||||
</wa-button>
|
||||
<wa-button size="small" appearance="filled" variant="neutral" href="https://github.com/shoelace-style/webawesome-alpha/discussions" target="_blank">
|
||||
<wa-icon slot="prefix" name="message-question"></wa-icon>
|
||||
Ask for help
|
||||
</wa-button>
|
||||
</div>
|
||||
{% endblock %}
|
||||
55
docs/_layouts/element.njk
Normal file
@@ -0,0 +1,55 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
|
||||
{% extends '../_includes/base.njk' %}
|
||||
|
||||
{# Component header #}
|
||||
{% block beforeContent %}
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
<div class="component-info">
|
||||
{% for tag, url in elements %}
|
||||
<code class="tag"><a href="{{ url }}">{{ tag }}</a></code>
|
||||
{% endfor %}
|
||||
{% if since %}<wa-badge variant="neutral">Since {{ since }}</wa-badge>{% endif %}
|
||||
{% if status %}
|
||||
<wa-badge
|
||||
{% if status == 'stable' %}variant="brand"{% endif %}
|
||||
{% if status == 'experimental' %}variant="warning"{% endif %}
|
||||
>
|
||||
{{ status }}
|
||||
</wa-badge>
|
||||
{% endif %}
|
||||
|
||||
{% if isPro %}
|
||||
<wa-badge class="pro">PRO</wa-badge>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if description -%}
|
||||
<p class="summary">{{ description | inlineMarkdown | safe }}</p>
|
||||
{%- endif %}
|
||||
{% if component %}
|
||||
<wa-callout variant="success">
|
||||
<wa-icon slot="icon" name="lightbulb" variant="regular"></wa-icon>
|
||||
Want to do more?
|
||||
Check out the {% for name in (component | toArray) -%}
|
||||
{{ ' and ' if loop.last and not loop.first }}<a href="/docs/components/{{ name }}"><code><wa-{{ name }}></code></a>{{ ', ' if not loop.last }}
|
||||
{%- endfor %} component{{ 's' if (component | isArray) }}</a>!
|
||||
</wa-callout>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{# Content #}
|
||||
{% block content %}
|
||||
{{ content | safe }}
|
||||
{% endblock %}
|
||||
|
||||
{# Component API #}
|
||||
{% block afterContent %}
|
||||
{# Slots #}
|
||||
{% if css_file %}
|
||||
<h2>Using these styles</h2>
|
||||
<p>If you want to use these styles without using the entirety of Web Awesome Natives, you can include the following CSS files:</p>
|
||||
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
4
docs/_layouts/page-wide.njk
Normal file
@@ -0,0 +1,4 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
|
||||
{% extends "../_includes/base-wide.njk" %}
|
||||
4
docs/_layouts/page.njk
Normal file
@@ -0,0 +1,4 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = false %}
|
||||
|
||||
{% extends "../_includes/base.njk" %}
|
||||
4
docs/_layouts/pattern.njk
Normal file
@@ -0,0 +1,4 @@
|
||||
{% set hasSidebar = true %}
|
||||
{% set hasOutline = true %}
|
||||
|
||||
{% extends "../_includes/base.njk" %}
|
||||
@@ -37,8 +37,7 @@ export function anchorHeadingsPlugin(options = {}) {
|
||||
}
|
||||
|
||||
// Look for headings
|
||||
let selector = `:is(${options.headingSelector}):not([data-no-anchor], [data-no-anchor] *)`;
|
||||
container.querySelectorAll(selector).forEach(heading => {
|
||||
container.querySelectorAll(options.headingSelector).forEach(heading => {
|
||||
const hasAnchor = heading.querySelector('a');
|
||||
const existingId = heading.getAttribute('id');
|
||||
const clone = parse(heading.outerHTML);
|
||||
190
docs/_utils/code-examples.js
Normal file
@@ -0,0 +1,190 @@
|
||||
import { parse } from 'node-html-parser';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const templates = {
|
||||
old(pre, code, { open, buttons, edit }) {
|
||||
const id = `code-example-${uuid().slice(-12)}`;
|
||||
let preview = code.textContent;
|
||||
|
||||
// Run preview scripts as modules to prevent collisions
|
||||
const root = parse(preview, { blockTextElements: { script: true } });
|
||||
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
|
||||
preview = root.toString();
|
||||
|
||||
return `
|
||||
<div class="code-example ${open ? 'open' : ''}">
|
||||
<div class="code-example-preview">
|
||||
${preview}
|
||||
</div>
|
||||
<div class="code-example-source" id="${id}">
|
||||
${pre.outerHTML}
|
||||
</div>
|
||||
${
|
||||
buttons
|
||||
? `
|
||||
<div class="code-example-buttons">
|
||||
<button
|
||||
class="code-example-toggle"
|
||||
type="button"
|
||||
aria-expanded="${open ? 'true' : 'false'}"
|
||||
aria-controls="${id}"
|
||||
>
|
||||
Code
|
||||
<wa-icon name="chevron-down"></wa-icon>
|
||||
</button>
|
||||
${
|
||||
edit
|
||||
? `
|
||||
<button class="code-example-pen" type="button">
|
||||
<wa-icon name="pen-to-square"></wa-icon>
|
||||
Edit
|
||||
</button>
|
||||
`
|
||||
: ''
|
||||
}
|
||||
`
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
new(pre, code, { open, first, attributes }) {
|
||||
attributes = {
|
||||
open,
|
||||
include: `link[rel=stylesheet][href^='/dist/']`,
|
||||
...attributes,
|
||||
};
|
||||
|
||||
const attributesString = Object.entries(attributes)
|
||||
.map(([key, value]) => {
|
||||
if (value === true) {
|
||||
return key;
|
||||
}
|
||||
if (value === false || value === null) {
|
||||
return '';
|
||||
}
|
||||
return `${key}="${value}"`;
|
||||
})
|
||||
.join(' ');
|
||||
|
||||
let includes = '';
|
||||
if (first) {
|
||||
includes = `
|
||||
<template class="wa-code-demo-include-isolated">
|
||||
<script src="/dist/webawesome.loader.js" type="module"></script>
|
||||
</template>`;
|
||||
}
|
||||
|
||||
let preview = '';
|
||||
if (attributes.viewport === undefined) {
|
||||
// Slot in pre-rendered preview
|
||||
preview = `<div style="display:contents" slot="preview">${code.textContent}</div>`;
|
||||
|
||||
// Run preview scripts as modules to prevent collisions
|
||||
const root = parse(preview, { blockTextElements: { script: true } });
|
||||
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
|
||||
preview = root.toString();
|
||||
}
|
||||
|
||||
return `${includes}
|
||||
<wa-code-demo ${attributesString}>
|
||||
${preview}
|
||||
${pre.outerHTML}
|
||||
</wa-code-demo>
|
||||
`;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Eleventy plugin to turn `<code class="example">` blocks into live examples.
|
||||
*/
|
||||
export function codeExamplesPlugin(eleventyConfig, options = {}) {
|
||||
const defaultOptions = {
|
||||
container: 'body',
|
||||
defaultOpen: (code, { outputPathIndex }) => {
|
||||
return (
|
||||
outputPathIndex === 1 && // is first
|
||||
code.textContent.length < 500
|
||||
); // is short
|
||||
},
|
||||
};
|
||||
options = { ...defaultOptions, ...options };
|
||||
|
||||
const stats = {
|
||||
inputPaths: {},
|
||||
outputPaths: {},
|
||||
};
|
||||
|
||||
eleventyConfig.addTransform('code-examples', function (content) {
|
||||
const { inputPath, outputPath } = this.page;
|
||||
|
||||
const doc = parse(content, { blockTextElements: { code: true } });
|
||||
const container = doc.querySelector(options.container);
|
||||
|
||||
if (!container) {
|
||||
return content;
|
||||
}
|
||||
|
||||
// Look for external links
|
||||
container.querySelectorAll('code.example').forEach(code => {
|
||||
stats.inputPaths[inputPath] ??= 0;
|
||||
stats.outputPaths[outputPath] ??= 0;
|
||||
stats.inputPaths[inputPath]++;
|
||||
stats.outputPaths[outputPath]++;
|
||||
|
||||
const pre = code.closest('pre');
|
||||
const first = stats.inputPaths[inputPath] === 1;
|
||||
|
||||
const localOptions = {
|
||||
...options,
|
||||
first,
|
||||
|
||||
// Modifier defaults
|
||||
edit: true,
|
||||
buttons: true,
|
||||
new: true, // comment this line to default back to the old demos
|
||||
attributes: {},
|
||||
};
|
||||
|
||||
for (const prop of ['new', 'open', 'buttons', 'edit']) {
|
||||
if (code.classList.contains(prop)) {
|
||||
localOptions[prop] = true;
|
||||
} else if (code.classList.contains(`no-${prop}`)) {
|
||||
localOptions[prop] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const attribute of ['viewport', 'include']) {
|
||||
if (code.hasAttribute(attribute)) {
|
||||
localOptions.attributes[attribute] = code.getAttribute(attribute);
|
||||
code.removeAttribute(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(localOptions.attributes).length > 0) {
|
||||
// attributes only work on the new syntax
|
||||
localOptions.new = true;
|
||||
}
|
||||
|
||||
if (localOptions.open === undefined) {
|
||||
if (localOptions.defaultOpen === true) {
|
||||
localOptions.open = localOptions.defaultOpen;
|
||||
} else if (typeof localOptions.defaultOpen === 'function') {
|
||||
localOptions.open = localOptions.defaultOpen(code, {
|
||||
pre,
|
||||
inputPathIndex: stats.inputPaths[inputPath],
|
||||
outputPathIndex: stats.outputPaths[outputPath],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const template = localOptions.new ? 'new' : 'old';
|
||||
const codeExample = parse(templates[template](pre, code, localOptions));
|
||||
|
||||
pre.replaceWith(codeExample);
|
||||
});
|
||||
|
||||
return doc.toString();
|
||||
});
|
||||
}
|
||||
32
docs/_utils/copy-code.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { parse } from 'node-html-parser';
|
||||
|
||||
/**
|
||||
* Eleventy plugin to add copy buttons to code blocks.
|
||||
*/
|
||||
export function copyCodePlugin(options = {}) {
|
||||
options = {
|
||||
container: 'body',
|
||||
...options,
|
||||
};
|
||||
|
||||
return function (eleventyConfig) {
|
||||
eleventyConfig.addTransform('copy-code', content => {
|
||||
const doc = parse(content, { blockTextElements: { code: true } });
|
||||
const container = doc.querySelector(options.container);
|
||||
|
||||
if (!container) {
|
||||
return content;
|
||||
}
|
||||
|
||||
// Look for code blocks
|
||||
container.querySelectorAll('pre > code').forEach(code => {
|
||||
const pre = code.closest('pre');
|
||||
|
||||
// Add a copy button (we set the copy data at runtime to reduce page bloat)
|
||||
pre.innerHTML = `<wa-copy-button class="copy-button" hoist></wa-copy-button>` + pre.innerHTML;
|
||||
});
|
||||
|
||||
return doc.toString();
|
||||
});
|
||||
};
|
||||
}
|
||||
79
docs/_utils/filters.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import { parse } from 'path';
|
||||
|
||||
export function stripExtension(string) {
|
||||
return parse(string).name;
|
||||
}
|
||||
|
||||
export function stripPrefix(content) {
|
||||
return content.replace(/^wa-/, '');
|
||||
}
|
||||
|
||||
// Trims whitespace and pipes from the start and end of a string. Useful for CEM types, which can be pipe-delimited.
|
||||
// With Prettier 3, this means a leading pipe will exist be present when the line wraps.
|
||||
export function trimPipes(content) {
|
||||
return typeof content === 'string' ? content.replace(/^(\s|\|)/g, '').replace(/(\s|\|)$/g, '') : content;
|
||||
}
|
||||
|
||||
export function keys(obj) {
|
||||
return Object.keys(obj);
|
||||
}
|
||||
|
||||
export function log(firstArg, ...rest) {
|
||||
console.log(firstArg, ...rest);
|
||||
return firstArg;
|
||||
}
|
||||
|
||||
function getCollection(name) {
|
||||
// From https://github.com/11ty/eleventy/blob/d3d24ccddb804e6e14773501d8c4e07e2c4b9c2b/src/Filters/GetLocaleCollectionItem.js#L39-L43
|
||||
return this.collections?.[name] || this.ctx?.collections?.[name] || this.context?.environments?.collections?.[name];
|
||||
}
|
||||
|
||||
export function getCollectionItemFromUrl(url, collection) {
|
||||
collection ??= getCollection.call(this, 'all') || [];
|
||||
return collection.find(item => item.url === url);
|
||||
}
|
||||
|
||||
export function getTitleFromUrl(url, collection) {
|
||||
const item = getCollectionItemFromUrl.call(this, url, collection);
|
||||
return item?.data.title || '';
|
||||
}
|
||||
|
||||
export function breadcrumbs(url, { withCurrent = false } = {}) {
|
||||
const parts = url.split('/').filter(Boolean);
|
||||
const ret = [];
|
||||
|
||||
while (parts.length) {
|
||||
let partialUrl = '/' + parts.join('/') + '/';
|
||||
let item = getCollectionItemFromUrl.call(this, partialUrl);
|
||||
|
||||
if (item && (partialUrl !== url || withCurrent)) {
|
||||
let title = item.data.title;
|
||||
if (title) {
|
||||
ret.unshift({ url: partialUrl, title });
|
||||
}
|
||||
}
|
||||
|
||||
parts.pop();
|
||||
|
||||
if (item?.data.parent) {
|
||||
let parentURL = item.data.parent;
|
||||
if (!item.data.parent.startsWith('/')) {
|
||||
// Parent is in the same directory
|
||||
parts.push(item.data.parent);
|
||||
parentURL = '/' + parts.join('/') + '/';
|
||||
}
|
||||
|
||||
let parentBreadcrumbs = breadcrumbs.call(this, parentURL, { withCurrent: true });
|
||||
return [...parentBreadcrumbs, ...ret];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function isArray(value) {
|
||||
return Array.isArray(value);
|
||||
}
|
||||
|
||||
export function toArray(value) {
|
||||
return isArray(value) ? value : [value];
|
||||
}
|
||||