mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 04:09:12 +00:00
[code-demo] Bugfixes
Slotted previews still don't work well with isolated demos :(
This commit is contained in:
@@ -80,9 +80,9 @@ const templates = {
|
||||
}
|
||||
|
||||
let preview = '';
|
||||
if (attributes.viewport === undefined) {
|
||||
preview = `<div style="display:contents" slot="preview">${code.textContent}</div>`;
|
||||
}
|
||||
// if (attributes.viewport === undefined) {
|
||||
preview = `<div style="display:contents" slot="preview">${code.textContent}</div>`;
|
||||
// }
|
||||
|
||||
return `${includes}
|
||||
<wa-code-demo ${attributesString}>
|
||||
|
||||
@@ -61,6 +61,10 @@ export default css`
|
||||
}
|
||||
}
|
||||
|
||||
wa-viewport-demo + slot[name='preview'].has-slotted {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#source {
|
||||
border-block-end: inherit;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import '../icon/icon.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { customElement, property, query } from 'lit/decorators.js';
|
||||
import { getInnerHTML, HasSlotController } from '../../internal/slot.js';
|
||||
import { html } from 'lit';
|
||||
@@ -78,11 +79,9 @@ export default class WaCodeDemo extends WebAwesomeElement {
|
||||
private readonly hasSlotController = new HasSlotController(this, 'preview');
|
||||
|
||||
render() {
|
||||
const code = this.getDemoHTML({ type: 'preview' });
|
||||
// FIXME Ideally we don't want to render the contents of the code element anywhere if a custom preview is provided.
|
||||
// NOTE We don't want to render the contents of the code element anywhere if a custom preview is provided.
|
||||
// That way, providing a custom preview can also be used to sanitize the code.
|
||||
const customPreview = this.hasUpdated ? this.hasSlotController.test('preview') : true;
|
||||
|
||||
const code = this.getDemoHTML({ type: 'preview' });
|
||||
let viewportHTML: string | TemplateResult = '';
|
||||
|
||||
if (this.viewport) {
|
||||
@@ -94,11 +93,14 @@ export default class WaCodeDemo extends WebAwesomeElement {
|
||||
`;
|
||||
}
|
||||
|
||||
const customPreview = this.hasUpdated ? this.hasSlotController.test('preview') : true;
|
||||
|
||||
return html`
|
||||
<div id="preview" part="preview">
|
||||
${viewportHTML}
|
||||
<slot
|
||||
name="preview"
|
||||
class=${classMap({ 'has-slotted': customPreview })}
|
||||
@slotchange=${this.handleSlotChange}
|
||||
.innerHTML=${customPreview || this.viewport ? '' : code}
|
||||
></slot>
|
||||
@@ -180,7 +182,7 @@ export default class WaCodeDemo extends WebAwesomeElement {
|
||||
let code;
|
||||
const customPreview = this.hasUpdated ? this.hasSlotController.test('preview') : true;
|
||||
if (options.type === 'preview' && customPreview && this.previewSlot) {
|
||||
code = getInnerHTML(this.previewSlot);
|
||||
code = getHTML(this.previewSlot.assignedNodes({ flatten: true }));
|
||||
} else {
|
||||
code = this.querySelector?.('code')?.textContent ?? this.textContent;
|
||||
}
|
||||
@@ -197,10 +199,12 @@ export default class WaCodeDemo extends WebAwesomeElement {
|
||||
private handleSlotChange(e: Event) {
|
||||
const slot = e.target as HTMLSlotElement;
|
||||
|
||||
if (slot.name === 'preview') {
|
||||
if (slot.name === 'preview' && !this.viewport) {
|
||||
const assignedNodes = slot.assignedNodes();
|
||||
|
||||
for (const node of assignedNodes) {
|
||||
// Unwrap templates
|
||||
// FIXME this will mess up the order of the nodes if there are mixed templates & regular nodes
|
||||
if (node.nodeName === 'TEMPLATE') {
|
||||
const content = (node as HTMLTemplateElement).content;
|
||||
const clone = content.cloneNode(true);
|
||||
@@ -360,3 +364,13 @@ function dedent(code: string) {
|
||||
|
||||
return code.replace(new RegExp(`^${minIndent}`, 'gm'), '');
|
||||
}
|
||||
|
||||
function getHTML(nodes: Iterable<Node>): string {
|
||||
return getInnerHTML(nodes, node => {
|
||||
if (node.nodeType === Node.ELEMENT_NODE && node.nodeName === 'TEMPLATE') {
|
||||
const template = node as HTMLTemplateElement;
|
||||
return template.innerHTML;
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,14 +61,24 @@ export class HasSlotController implements ReactiveController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a slot, this function iterates over all of its assigned element and text nodes and returns the concatenated
|
||||
* HTML as a string. This is useful because we can't use slot.innerHTML as an alternative.
|
||||
* Given a list of nodes, this function iterates over all of them and returns the concatenated
|
||||
* HTML as a string. This is useful for getting the HTML that corresponds to a slot’s assigned nodes (since we can't use slot.innerHTML as an alternative).
|
||||
* @param nodes - The list of nodes to iterate over.
|
||||
* @param callback - A function that can be used to customize the HTML output for specific types of nodes. If the function returns undefined, the default HTML output will be used.
|
||||
*/
|
||||
export function getInnerHTML(slot: HTMLSlotElement): string {
|
||||
const nodes = slot.assignedNodes({ flatten: true });
|
||||
export function getInnerHTML(nodes: Iterable<Node>, callback?: (node: Node) => string | undefined): string {
|
||||
let html = '';
|
||||
|
||||
[...nodes].forEach(node => {
|
||||
for (const node of nodes) {
|
||||
if (callback) {
|
||||
const customHTML = callback(node);
|
||||
|
||||
if (customHTML !== undefined) {
|
||||
html += customHTML;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
html += (node as HTMLElement).outerHTML;
|
||||
}
|
||||
@@ -76,7 +86,7 @@ export function getInnerHTML(slot: HTMLSlotElement): string {
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
html += node.textContent;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user