2020-07-15 21:30:37 +00:00
|
|
|
(() => {
|
|
|
|
let metadataStore;
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
function getAttrName(propName) {
|
|
|
|
return propName.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`).replace(/^-/, '');
|
|
|
|
}
|
|
|
|
|
2020-07-15 21:30:37 +00:00
|
|
|
function createPropsTable(props) {
|
|
|
|
const table = document.createElement('table');
|
|
|
|
table.innerHTML = `
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Property</th>
|
|
|
|
<th>Description</th>
|
|
|
|
<th>Type</th>
|
|
|
|
<th>Default</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
${props
|
2021-02-26 14:09:13 +00:00
|
|
|
.map(prop => {
|
|
|
|
const attr = getAttrName(prop.name);
|
|
|
|
return `
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<code>${escapeHtml(prop.name)}</code>
|
|
|
|
${
|
|
|
|
prop.name !== attr
|
|
|
|
? `
|
|
|
|
<br>
|
|
|
|
<small>
|
2021-03-07 14:20:04 +00:00
|
|
|
<sl-tooltip content="Use this attribute in your HTML">
|
2021-02-26 14:09:13 +00:00
|
|
|
<code class="attribute-tooltip">${escapeHtml(attr)}</code>
|
|
|
|
</sl-tooltip>
|
|
|
|
</small>`
|
|
|
|
: ''
|
|
|
|
}
|
|
|
|
</td>
|
|
|
|
<td>${escapeHtml(prop.description)}</td>
|
|
|
|
<td><code style="white-space: normal;">${escapeHtml(prop.type)}</code></td>
|
|
|
|
<td><code style="white-space: normal;">${escapeHtml(prop.defaultValue)}</code></td>
|
|
|
|
</tr>
|
|
|
|
`;
|
|
|
|
})
|
2020-07-15 21:30:37 +00:00
|
|
|
.join('')}
|
|
|
|
</tbody>
|
|
|
|
`;
|
|
|
|
|
|
|
|
return table.outerHTML;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createEventsTable(events) {
|
|
|
|
const table = document.createElement('table');
|
|
|
|
table.innerHTML = `
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Event</th>
|
|
|
|
<th>Description</th>
|
2021-03-07 14:10:45 +00:00
|
|
|
<th>Details</th>
|
2020-07-15 21:30:37 +00:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
${events
|
|
|
|
.map(
|
|
|
|
event => `
|
|
|
|
<tr>
|
2021-02-26 14:09:13 +00:00
|
|
|
<td><code>${escapeHtml(event.name)}</code></td>
|
|
|
|
<td>${escapeHtml(event.description)}</td>
|
2021-03-06 17:01:39 +00:00
|
|
|
<td><code style="white-space: normal;">${escapeHtml(event.details)}</code></td>
|
2020-07-15 21:30:37 +00:00
|
|
|
</tr>
|
|
|
|
`
|
|
|
|
)
|
|
|
|
.join('')}
|
|
|
|
</tbody>
|
|
|
|
`;
|
|
|
|
|
|
|
|
return table.outerHTML;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createMethodsTable(methods) {
|
|
|
|
const table = document.createElement('table');
|
|
|
|
table.innerHTML = `
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Method</th>
|
|
|
|
<th>Description</th>
|
2021-02-26 14:09:13 +00:00
|
|
|
<th>Arguments</th>
|
2020-07-15 21:30:37 +00:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
${methods
|
|
|
|
.map(
|
|
|
|
method => `
|
2021-02-26 14:09:13 +00:00
|
|
|
<tr>
|
|
|
|
<td><code>${escapeHtml(method.name)}</code></td>
|
|
|
|
<td>${escapeHtml(method.description)}</td>
|
|
|
|
<td>
|
|
|
|
${
|
|
|
|
method.params.length
|
|
|
|
? `
|
|
|
|
<code style="white-space: normal;">${escapeHtml(
|
|
|
|
method.params.map(param => `${param.name}: ${param.type}`).join(', ')
|
|
|
|
)}</code>
|
|
|
|
`
|
|
|
|
: ''
|
|
|
|
}
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
`
|
2020-07-15 21:30:37 +00:00
|
|
|
)
|
|
|
|
.join('')}
|
|
|
|
</tbody>
|
|
|
|
`;
|
|
|
|
|
|
|
|
return table.outerHTML;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createSlotsTable(slots) {
|
|
|
|
const table = document.createElement('table');
|
|
|
|
table.innerHTML = `
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Slot</th>
|
|
|
|
<th>Description</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
${slots
|
|
|
|
.map(
|
|
|
|
slot => `
|
|
|
|
<tr>
|
|
|
|
<td><code>${slot.name ? escapeHtml(slot.name) : '(default)'}</code></td>
|
2021-02-26 14:09:13 +00:00
|
|
|
<td>${escapeHtml(slot.description)}</td>
|
2020-07-15 21:30:37 +00:00
|
|
|
</tr>
|
|
|
|
`
|
|
|
|
)
|
|
|
|
.join('')}
|
|
|
|
</tbody>
|
|
|
|
`;
|
|
|
|
|
|
|
|
return table.outerHTML;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createCustomPropertiesTable(styles) {
|
|
|
|
const table = document.createElement('table');
|
|
|
|
table.innerHTML = `
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Name</th>
|
|
|
|
<th>Description</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
${styles
|
|
|
|
.map(
|
|
|
|
style => `
|
|
|
|
<tr>
|
2020-07-16 11:25:28 +00:00
|
|
|
<td><code>${escapeHtml(style.name)}</code></td>
|
2021-02-26 14:09:13 +00:00
|
|
|
<td>${escapeHtml(style.description)}</td>
|
2020-07-15 21:30:37 +00:00
|
|
|
</tr>
|
|
|
|
`
|
|
|
|
)
|
|
|
|
.join('')}
|
|
|
|
</tbody>
|
|
|
|
`;
|
|
|
|
|
|
|
|
return table.outerHTML;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createPartsTable(parts) {
|
|
|
|
const table = document.createElement('table');
|
|
|
|
table.innerHTML = `
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Name</th>
|
|
|
|
<th>Description</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
${parts
|
|
|
|
.map(
|
|
|
|
part => `
|
|
|
|
<tr>
|
|
|
|
<td><code>${escapeHtml(part.name)}</code></td>
|
2021-02-26 14:09:13 +00:00
|
|
|
<td>${escapeHtml(part.description)}</td>
|
2020-07-15 21:30:37 +00:00
|
|
|
</tr>
|
|
|
|
`
|
|
|
|
)
|
|
|
|
.join('')}
|
|
|
|
</tbody>
|
|
|
|
`;
|
|
|
|
|
|
|
|
return table.outerHTML;
|
|
|
|
}
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
function createDependenciesList(targetComponent, allComponents) {
|
2021-01-06 17:59:36 +00:00
|
|
|
const ul = document.createElement('ul');
|
2021-02-26 14:09:13 +00:00
|
|
|
const dependencies = [];
|
2021-01-06 17:59:36 +00:00
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
// Recursively fetch subdependencies
|
|
|
|
function getDependencies(tag) {
|
|
|
|
const component = allComponents.find(c => c.tag === tag);
|
2021-04-07 16:56:44 +00:00
|
|
|
if (!component || !Array.isArray(component.dependencies)) {
|
2021-02-26 14:09:13 +00:00
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
component.dependencies.map(tag => {
|
|
|
|
if (!dependencies.includes(tag)) {
|
|
|
|
dependencies.push(tag);
|
2021-01-06 18:25:59 +00:00
|
|
|
}
|
2021-02-26 14:09:13 +00:00
|
|
|
getDependencies(tag);
|
2021-01-06 18:25:59 +00:00
|
|
|
});
|
2021-02-26 14:09:13 +00:00
|
|
|
}
|
2021-01-06 17:59:36 +00:00
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
getDependencies(targetComponent);
|
|
|
|
dependencies.sort().map(tag => {
|
2021-01-06 18:25:59 +00:00
|
|
|
const li = document.createElement('li');
|
2021-02-26 14:09:13 +00:00
|
|
|
li.innerHTML = `<code><${tag}></code>`;
|
2021-01-06 18:25:59 +00:00
|
|
|
ul.appendChild(li);
|
|
|
|
});
|
2020-07-15 21:30:37 +00:00
|
|
|
|
|
|
|
return ul.outerHTML;
|
|
|
|
}
|
|
|
|
|
|
|
|
function escapeHtml(html) {
|
|
|
|
return (html + '')
|
|
|
|
.replace(/&/g, '&')
|
|
|
|
.replace(/</g, '<')
|
|
|
|
.replace(/>/g, '>')
|
|
|
|
.replace(/"/g, '"')
|
|
|
|
.replace(/'/g, ''')
|
|
|
|
.replace(/`(.*?)`/g, '<code>$1</code>');
|
|
|
|
}
|
|
|
|
|
|
|
|
function getMetadata() {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
// Simple caching to prevent multiple XHR requests
|
|
|
|
if (metadataStore) {
|
|
|
|
return resolve(metadataStore);
|
|
|
|
}
|
|
|
|
|
2021-03-25 12:15:26 +00:00
|
|
|
fetch('/dist/metadata.json')
|
2020-07-15 21:30:37 +00:00
|
|
|
.then(res => res.json())
|
|
|
|
.then(data => {
|
|
|
|
metadataStore = data;
|
|
|
|
resolve(metadataStore);
|
|
|
|
})
|
|
|
|
.catch(err => console.error(err));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!window.$docsify) {
|
|
|
|
throw new Error('Docsify must be loaded before installing this plugin.');
|
|
|
|
}
|
|
|
|
|
|
|
|
window.$docsify.plugins.push((hook, vm) => {
|
|
|
|
hook.mounted(function () {
|
2021-02-26 14:09:13 +00:00
|
|
|
getMetadata().then(metadata => {
|
|
|
|
const target = document.querySelector('.app-name');
|
|
|
|
|
|
|
|
// Add version
|
|
|
|
const version = document.createElement('div');
|
|
|
|
version.classList.add('sidebar-version');
|
|
|
|
version.textContent = metadata.version;
|
|
|
|
target.appendChild(version);
|
|
|
|
|
|
|
|
// Add repo buttons
|
|
|
|
const buttons = document.createElement('div');
|
|
|
|
buttons.classList.add('sidebar-buttons');
|
|
|
|
buttons.innerHTML = `
|
2020-07-29 14:37:22 +00:00
|
|
|
<a class="repo-button repo-button--small repo-button--sponsor" href="https://github.com/sponsors/claviska" rel="noopener" target="_blank">
|
|
|
|
<sl-icon name="heart"></sl-icon> Sponsor
|
|
|
|
</a>
|
|
|
|
<a class="repo-button repo-button--small repo-button--github" href="https://github.com/shoelace-style/shoelace/stargazers" rel="noopener" target="_blank">
|
2021-02-26 14:09:13 +00:00
|
|
|
<sl-icon name="github"></sl-icon> <span class="github-star-count">Star</span>
|
2020-07-29 14:37:22 +00:00
|
|
|
</a>
|
|
|
|
<a class="repo-button repo-button--small repo-button--twitter" href="https://twitter.com/shoelace_style" rel="noopener" target="_blank">
|
2021-02-26 14:09:13 +00:00
|
|
|
<sl-icon name="twitter"></sl-icon> Follow
|
2020-07-29 14:37:22 +00:00
|
|
|
</a>
|
|
|
|
`;
|
2021-02-26 14:09:13 +00:00
|
|
|
target.appendChild(buttons);
|
|
|
|
});
|
2020-07-15 21:30:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
hook.beforeEach(async function (content, next) {
|
|
|
|
const metadata = await getMetadata();
|
|
|
|
|
|
|
|
// Replace %VERSION% placeholders
|
|
|
|
content = content.replace(/%VERSION%/g, metadata.version);
|
|
|
|
|
|
|
|
// Handle [component-header] tags
|
|
|
|
content = content.replace(/\[component-header:([a-z-]+)\]/g, (match, tag) => {
|
2021-02-26 14:09:13 +00:00
|
|
|
const component = metadata.components.filter(data => data.tag === tag)[0];
|
2020-07-15 21:30:37 +00:00
|
|
|
let result = '';
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (!component) {
|
2020-07-15 21:30:37 +00:00
|
|
|
console.error('Component not found in metadata: ' + tag);
|
|
|
|
next(content);
|
|
|
|
}
|
|
|
|
|
2020-10-16 11:36:43 +00:00
|
|
|
let badgeType = 'info';
|
2021-02-26 14:09:13 +00:00
|
|
|
if (component.status === 'stable') badgeType = 'primary';
|
|
|
|
if (component.status === 'experimental') badgeType = 'warning';
|
|
|
|
if (component.status === 'planned') badgeType = 'info';
|
|
|
|
if (component.status === 'deprecated') badgeType = 'danger';
|
2020-07-15 21:30:37 +00:00
|
|
|
|
2020-10-16 11:36:43 +00:00
|
|
|
result += `
|
|
|
|
<div class="component-header">
|
|
|
|
<div class="component-header__tag">
|
2021-02-26 14:09:13 +00:00
|
|
|
<code>${component.className} | <${component.tag}></code>
|
2020-07-15 21:30:37 +00:00
|
|
|
</div>
|
2020-10-16 11:36:43 +00:00
|
|
|
|
|
|
|
<div class="component-header__info">
|
|
|
|
<sl-badge type="info" pill>
|
2021-02-26 14:09:13 +00:00
|
|
|
Since ${component.since || '?'}
|
2020-10-16 11:36:43 +00:00
|
|
|
</sl-badge>
|
|
|
|
|
|
|
|
<sl-badge type="${badgeType}" pill style="text-transform: capitalize;">
|
2021-02-26 14:09:13 +00:00
|
|
|
${component.status}
|
2020-10-16 11:36:43 +00:00
|
|
|
</sl-badge>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
`;
|
2020-07-15 21:30:37 +00:00
|
|
|
|
|
|
|
return result.replace(/^ +| +$/gm, '');
|
|
|
|
});
|
|
|
|
|
|
|
|
// Handle [component-metadata] tags
|
|
|
|
content = content.replace(/\[component-metadata:([a-z-]+)\]/g, (match, tag) => {
|
2021-02-26 14:09:13 +00:00
|
|
|
const component = metadata.components.filter(data => data.tag === tag)[0];
|
2020-07-15 21:30:37 +00:00
|
|
|
let result = '';
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (!component) {
|
2020-07-15 21:30:37 +00:00
|
|
|
console.error('Component not found in metadata: ' + tag);
|
|
|
|
next(content);
|
|
|
|
}
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (component.props.length) {
|
2020-07-15 21:30:37 +00:00
|
|
|
result += `
|
|
|
|
## Properties
|
2021-02-26 14:09:13 +00:00
|
|
|
${createPropsTable(component.props)}
|
2020-07-15 21:30:37 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (component.events.length) {
|
2020-07-15 21:30:37 +00:00
|
|
|
result += `
|
|
|
|
## Events
|
2021-02-26 14:09:13 +00:00
|
|
|
${createEventsTable(component.events)}
|
2020-07-15 21:30:37 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (component.methods.length) {
|
2020-07-15 21:30:37 +00:00
|
|
|
result += `
|
|
|
|
## Methods
|
2021-02-26 14:09:13 +00:00
|
|
|
${createMethodsTable(component.methods)}
|
2020-07-15 21:30:37 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (component.slots.length) {
|
2020-07-15 21:30:37 +00:00
|
|
|
result += `
|
|
|
|
## Slots
|
2021-02-26 14:09:13 +00:00
|
|
|
${createSlotsTable(component.slots)}
|
2020-07-15 21:30:37 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (component.cssCustomProperties.length) {
|
2020-07-15 21:30:37 +00:00
|
|
|
result += `
|
|
|
|
## CSS Custom Properties
|
2021-02-26 14:09:13 +00:00
|
|
|
${createCustomPropertiesTable(component.cssCustomProperties)}
|
2020-07-15 21:30:37 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (component.parts.length) {
|
2020-07-15 21:30:37 +00:00
|
|
|
result += `
|
|
|
|
## CSS Parts
|
2021-02-26 14:09:13 +00:00
|
|
|
${createPartsTable(component.parts)}
|
2020-07-15 21:30:37 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
if (component.dependencies.length) {
|
2020-07-15 21:30:37 +00:00
|
|
|
result += `
|
2021-01-06 17:59:36 +00:00
|
|
|
## Dependencies
|
2020-07-15 21:30:37 +00:00
|
|
|
|
2021-03-06 17:01:39 +00:00
|
|
|
This component has the following dependencies so, if you're [cherry picking](/getting-started/installation#cherry-picking),
|
2021-02-26 14:09:13 +00:00
|
|
|
be sure to import these components in addition to <code><${tag}></code>.
|
2020-07-15 21:30:37 +00:00
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
${createDependenciesList(component.tag, metadata.components)}
|
2020-07-15 21:30:37 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Strip whitespace so markdown doesn't process things as code blocks
|
|
|
|
return result.replace(/^ +| +$/gm, '');
|
|
|
|
});
|
|
|
|
|
|
|
|
next(content);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
})();
|