mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-19 07:29:14 +00:00
Compare commits
5 Commits
css-attrib
...
components
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d85842c766 | ||
|
|
8e3a525b4e | ||
|
|
068f9314e6 | ||
|
|
c6a9405c19 | ||
|
|
4ae21c9537 |
@@ -10,7 +10,7 @@ import { replaceTextPlugin } from './_utils/replace-text.js';
|
|||||||
import { searchPlugin } from './_utils/search.js';
|
import { searchPlugin } from './_utils/search.js';
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile } from 'fs/promises';
|
||||||
import { outlinePlugin } from './_utils/outline.js';
|
import { outlinePlugin } from './_utils/outline.js';
|
||||||
import { getComponents } from './_utils/manifest.js';
|
import componentList from './_data/componentList.js';
|
||||||
import litPlugin from '@lit-labs/eleventy-plugin-lit';
|
import litPlugin from '@lit-labs/eleventy-plugin-lit';
|
||||||
|
|
||||||
import process from 'process';
|
import process from 'process';
|
||||||
@@ -46,16 +46,6 @@ export default function (eleventyConfig) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
eleventyConfig.addNunjucksGlobal('getComponent', tagName => {
|
|
||||||
const component = getComponents().find(c => c.tagName === tagName);
|
|
||||||
|
|
||||||
if (!component) {
|
|
||||||
throw new Error(
|
|
||||||
`Unable to find "<${tagName}>". Make sure the file name is the same as the tag name (without prefix).`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return component;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Use our own markdown instance
|
// Use our own markdown instance
|
||||||
eleventyConfig.setLibrary('md', markdown);
|
eleventyConfig.setLibrary('md', markdown);
|
||||||
@@ -115,8 +105,7 @@ export default function (eleventyConfig) {
|
|||||||
// mutation-observer (why SSR this?)
|
// mutation-observer (why SSR this?)
|
||||||
// resize-observer (why SSR this?)
|
// resize-observer (why SSR this?)
|
||||||
// tooltip (why SSR this?)
|
// tooltip (why SSR this?)
|
||||||
|
const componentModules = componentList
|
||||||
const componentModules = getComponents()
|
|
||||||
// .filter(component => !omittedModules.includes(component.tagName.split(/wa-/)[1]))
|
// .filter(component => !omittedModules.includes(component.tagName.split(/wa-/)[1]))
|
||||||
.map(component => {
|
.map(component => {
|
||||||
const name = component.tagName.split(/wa-/)[1];
|
const name = component.tagName.split(/wa-/)[1];
|
||||||
|
|||||||
75
docs/_data/componentList.js
Normal file
75
docs/_data/componentList.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* @module components Fetches components from custom-elements.json and exposes them in a saner format.
|
||||||
|
*/
|
||||||
|
import { dirname, resolve } from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
const manifest = JSON.parse(readFileSync(resolve(__dirname, '../../dist/custom-elements.json'), 'utf-8'));
|
||||||
|
|
||||||
|
const components = manifest.modules.flatMap(module => {
|
||||||
|
return module.declarations
|
||||||
|
.filter(c => c?.customElement)
|
||||||
|
.map(declaration => {
|
||||||
|
// Generate the dist path based on the src path and attach it to the component
|
||||||
|
declaration.path = module.path.replace(/^src\//, 'dist/').replace(/\.ts$/, '.js');
|
||||||
|
|
||||||
|
// Remove private members and those that lack a description
|
||||||
|
const members = declaration.members?.filter(member => member.description && member.privacy !== 'private');
|
||||||
|
|
||||||
|
const methods = members?.filter(prop => prop.kind === 'method' && prop.privacy !== 'private');
|
||||||
|
const attributes = declaration.attributes ?? [];
|
||||||
|
const properties = members?.filter(prop => {
|
||||||
|
// Look for a corresponding attribute
|
||||||
|
const attribute = attributes?.find(attr => attr.fieldName === prop.name);
|
||||||
|
if (attribute) {
|
||||||
|
prop.attribute = attribute.name || attribute.fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop.kind === 'field' && prop.privacy !== 'private';
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...declaration,
|
||||||
|
slug: declaration.tagName.replace(/^wa-/, ''),
|
||||||
|
methods,
|
||||||
|
attributes,
|
||||||
|
properties
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Build dependency graphs
|
||||||
|
components.forEach(component => {
|
||||||
|
const dependencies = [];
|
||||||
|
|
||||||
|
// Recursively fetch sub-dependencies
|
||||||
|
function getDependencies(tag) {
|
||||||
|
const cmp = components.find(c => c.tagName === tag);
|
||||||
|
if (!cmp || !Array.isArray(component.dependencies)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmp.dependencies?.forEach(dependentTag => {
|
||||||
|
if (!dependencies.includes(dependentTag)) {
|
||||||
|
dependencies.push(dependentTag);
|
||||||
|
}
|
||||||
|
getDependencies(dependentTag);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getDependencies(component.tagName);
|
||||||
|
|
||||||
|
component.dependencies = dependencies.sort();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort by name
|
||||||
|
components.sort((a, b) => {
|
||||||
|
if (a.name < b.name) return -1;
|
||||||
|
if (a.name > b.name) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
export default components;
|
||||||
3
docs/_data/components.js
Normal file
3
docs/_data/components.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import componentList from './componentList.js';
|
||||||
|
|
||||||
|
export default Object.fromEntries(componentList.map(component => [component.slug, component]));
|
||||||
43
docs/_data/componentsBy.js
Normal file
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));
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{% set hasSidebar = true %}
|
{% set hasSidebar = true %}
|
||||||
{% set hasOutline = true %}
|
{% set hasOutline = true %}
|
||||||
{% set component = getComponent('wa-' + page.fileSlug) %}
|
{% set component = components[page.fileSlug] %}
|
||||||
{% set description = component.summary %}
|
{% set description = component.summary %}
|
||||||
|
|
||||||
{% extends '../_includes/base.njk' %}
|
{% extends '../_includes/base.njk' %}
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
import { fileURLToPath } from 'url';
|
|
||||||
import { dirname, resolve } from 'path';
|
|
||||||
import { readFileSync } from 'fs';
|
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
||||||
|
|
||||||
const manifest = JSON.parse(readFileSync(resolve(__dirname, '../../dist/custom-elements.json'), 'utf-8'));
|
|
||||||
/**
|
|
||||||
* @returns Fetches components from custom-elements.json and returns them in more sane format.
|
|
||||||
*/
|
|
||||||
export function getComponents() {
|
|
||||||
const components = [];
|
|
||||||
|
|
||||||
manifest.modules?.forEach(module => {
|
|
||||||
module.declarations?.forEach(declaration => {
|
|
||||||
if (declaration.customElement) {
|
|
||||||
// Generate the dist path based on the src path and attach it to the component
|
|
||||||
declaration.path = module.path.replace(/^src\//, 'dist/').replace(/\.ts$/, '.js');
|
|
||||||
|
|
||||||
// Remove private members and those that lack a description
|
|
||||||
const members = declaration.members?.filter(member => member.description && member.privacy !== 'private');
|
|
||||||
const methods = members?.filter(prop => prop.kind === 'method' && prop.privacy !== 'private');
|
|
||||||
const properties = members?.filter(prop => {
|
|
||||||
// Look for a corresponding attribute
|
|
||||||
const attribute = declaration.attributes?.find(attr => attr.fieldName === prop.name);
|
|
||||||
if (attribute) {
|
|
||||||
prop.attribute = attribute.name || attribute.fieldName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return prop.kind === 'field' && prop.privacy !== 'private';
|
|
||||||
});
|
|
||||||
components.push({
|
|
||||||
...declaration,
|
|
||||||
methods,
|
|
||||||
properties
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Build dependency graphs
|
|
||||||
components.forEach(component => {
|
|
||||||
const dependencies = [];
|
|
||||||
|
|
||||||
// Recursively fetch sub-dependencies
|
|
||||||
function getDependencies(tag) {
|
|
||||||
const cmp = components.find(c => c.tagName === tag);
|
|
||||||
if (!cmp || !Array.isArray(component.dependencies)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmp.dependencies?.forEach(dependentTag => {
|
|
||||||
if (!dependencies.includes(dependentTag)) {
|
|
||||||
dependencies.push(dependentTag);
|
|
||||||
}
|
|
||||||
getDependencies(dependentTag);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getDependencies(component.tagName);
|
|
||||||
|
|
||||||
component.dependencies = dependencies.sort();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sort by name
|
|
||||||
return components.sort((a, b) => {
|
|
||||||
if (a.name < b.name) return -1;
|
|
||||||
if (a.name > b.name) return 1;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
34
docs/docs/components/reference.njk
Normal file
34
docs/docs/components/reference.njk
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
title: Component Reference
|
||||||
|
layout: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table code {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{% for type, all in componentsBy -%}
|
||||||
|
<h2>All {{ "CSS custom properties" if type == "cssProperty" else ("CSS parts" if type == "cssPart" else (type | title) + "s") }}</h2>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Components</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% for name, thingComponents in all -%}
|
||||||
|
<tr>
|
||||||
|
<th><code>{{ name }}{{ "()" if type == "method" }}</code></th>
|
||||||
|
<td>
|
||||||
|
{% for component in thingComponents %}
|
||||||
|
<a href="../{{ component.slug }}"><code><{{ component.tagName }}></code></a>
|
||||||
|
{%- endfor -%}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{%- endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{%- endfor %}
|
||||||
Reference in New Issue
Block a user