Skip to content

Commit

Permalink
docs(tile): split out demos (#1291)
Browse files Browse the repository at this point in the history
  • Loading branch information
bennypowers authored Oct 26, 2023
1 parent b3f7b18 commit 5e64235
Show file tree
Hide file tree
Showing 224 changed files with 4,195 additions and 4,899 deletions.
4 changes: 4 additions & 0 deletions .changeset/alert-button-link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
"@rhds/element": patch
---
`<rh-alert>`: fix `<rh-button variant="link">` as slotted action
4 changes: 4 additions & 0 deletions .changeset/audio-hebrew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
"@rhds/elements": minor
---
`<rh-audio-player>`: added Hebrew translations
4 changes: 4 additions & 0 deletions .changeset/menu-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
"@rhds/elements": patch
---
`<rh-menu>`: support color context
4 changes: 4 additions & 0 deletions .changeset/rh-dialog-always-light.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
"@rhds/elements": patch
---
`<rh-dialog>`: ensure dialog content is always on light theme
158 changes: 124 additions & 34 deletions docs/_data/playgrounds.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ const DEMO_SUBRESOURCE_RE = /(?<attr>href|src)="\/elements\/rh-(?<unprefixed>.*)
*/
const DEMO_FILEPATH_IS_MAIN_DEMO_RE = /\/elements\/(.*)\/demo\/\1\.html/;

/**
* Elements which can support a `src=""` attribute which points to a subresource
*/
const SRC_SUBRESOURCE_TAGNAMES = new Set([
'img',
'rh-avatar',
]);

/**
* Replace paths in demo files from the dev SPA's format to 11ty's format
* @param {string} content
Expand All @@ -56,8 +64,7 @@ function demoPaths(content, pathname) {
function isModuleScript(node) {
return (
node.tagName === 'script' &&
node.attrs.some(x => x.name === 'type' && x.value === 'module') &&
node.attrs.some(x => x.name === 'src')
node.attrs.some(x => x.name === 'type' && x.value === 'module')
);
}

Expand All @@ -69,11 +76,34 @@ function isStyleLink(node) {
);
}

function hasLocalSrcAttr(node) {
return (
node.attrs.some(({ name, value }) => name === 'src' && !value.startsWith('http'))
);
}

function getAttrMap(node) {
return Object.fromEntries(node.attrs.map(({ name, value }) =>
[name, value]));
}

class SubresourceError extends Error {
constructor(message, originalError, subresourceFileURL) {
super(message);
this.originalError = originalError;
this.subresourceFileURL = subresourceFileURL;
}
}

module.exports = async function(data) {
performance.mark('playgrounds-start');
const { parseFragment, serialize } = await import('parse5');
const Tools = await import('@parse5/tools');

function append(node, ...nodes) {
Tools.spliceChildren(node, Infinity, 0, ...nodes);
}

const demoManifests = groupBy('primaryElementName', data.demos);

const playgroundConfigsMap = new Map();
Expand All @@ -95,11 +125,17 @@ module.exports = async function(data) {

const baseCssPathPrefix = demo.filePath.match(DEMO_FILEPATH_IS_MAIN_DEMO_RE) ? '' : '../';

Tools.spliceChildren(
append(
fragment,
Infinity,
0,
Tools.createCommentNode('playground-fold'),
Tools.createElement('link', {
rel: 'stylesheet',
href: 'https://static.redhat.com/libs/redhat/redhat-font/4/webfonts/red-hat-font.min.css'
}),
Tools.createElement('link', {
rel: 'stylesheet',
href: 'https://static.redhat.com/libs/redhat/redhat-theme/6/advanced-theme.css'
}),
Tools.createElement('link', {
rel: 'stylesheet',
href: `${baseCssPathPrefix}rhds-demo-base.css`,
Expand All @@ -116,51 +152,105 @@ module.exports = async function(data) {
const isMainDemo = filename === 'demo/index.html';
const demoSlug = filename.split('/').at(1);

const addSubresourceURL = async subresourceURL => {
if (subresourceURL && !subresourceURL.startsWith('http')) {
const subresourceFileURL = !subresourceURL.startsWith('/')
// non-tabular ternary
// eslint-disable-next-line operator-linebreak
? new URL(subresourceURL, base)
: new URL(subresourceURL.replace('/', './'), docsDir);
try {
const resourceName =
path.normalize(`demo${isMainDemo ? '' : `/${demoSlug}`}/${subresourceURL}`);
if (!fileMap.has(resourceName)) {
const content =
demoPaths(
await fs.readFile(subresourceFileURL, 'utf8'),
subresourceFileURL.pathname,
);
fileMap.set(resourceName, { content, hidden: true });
}
} catch (e) {
throw new SubresourceError(`Error generating playground for ${demo.slug}.\nCould not find subresource ${subresourceURL} at ${subresourceFileURL?.href ?? 'unknown'}`, e, subresourceFileURL);
}
}
};

fileMap.set('demo/rhds-demo-base.css', {
contentType: 'text/css',
content: baseCssSource,
hidden: true,
});

fileMap.set(filename, {
contentType: 'text/html',
selected: isMainDemo,
content: demoPaths(serialize(fragment), demo.filePath),
label: demo.title,
});

const modulesAndLinks = Tools.queryAll(fragment, node =>
const hrefSubresourceElements = Tools.queryAll(fragment, node =>
Tools.isElementNode(node) &&
isModuleScript(node) ||
isStyleLink(node));

// register demo script and css resources
for (const el of modulesAndLinks) {
const isLink = el.tagName === 'link';
const attrs = Object.fromEntries(el.attrs.map(({ name, value }) => [name, value]));
const subresourceURL = isLink ? attrs.href : attrs.src;
if (!subresourceURL.startsWith('http')) {
const subresourceFileURL = !subresourceURL.startsWith('/')
// non-tabular tern
// eslint-disable-next-line operator-linebreak
? new URL(subresourceURL, base)
: new URL(subresourceURL.replace('/', './'), docsDir);
try {
const content = demoPaths(await fs.readFile(subresourceFileURL, 'utf8'), subresourceFileURL.pathname);
const resourceName = path.normalize(`demo${isMainDemo ? '' : `/${demoSlug}`}/${subresourceURL}`);
fileMap.set(resourceName, { content, hidden: true });
} catch (e) {
// we can swallow the error for the demo base file because we wrote it ourselves above.
// maybe not the most elegant solution, but it works
if (subresourceFileURL?.href?.endsWith('rhds-demo-base.css')) { continue; }
const srcSubresourceElements = Tools.queryAll(fragment, node =>
Tools.isElementNode(node) &&
SRC_SUBRESOURCE_TAGNAMES.has(node.tagName) &&
hasLocalSrcAttr(node));

// register demo css resources
for (const el of hrefSubresourceElements) {
try {
const attrs = getAttrMap(el);
await addSubresourceURL(attrs.href);
} catch (e) {
// we can swallow the error for the demo base file because we wrote it ourselves above.
// maybe not the most elegant solution, but it works
if (e.subresourceFileURL?.href?.endsWith('rhds-demo-base.css')) {
continue;
} else {
// In order to surface the error to the user, let's enable console logging
// eslint-disable-next-line no-console
console.log(`Error generating playground for ${demo.slug}.\nCould not find subresource ${subresourceURL} at ${subresourceFileURL?.href ?? 'unknown'}`);
console.log(e.message);
throw e;
}
}
}

// register demo script and image resources
for (const el of srcSubresourceElements) {
const attrs = getAttrMap(el);
await addSubresourceURL(attrs.src);
}

// HACK: https://github.com/google/playground-elements/issues/93#issuecomment-1775247123
const inlineModules =
Tools.queryAll(fragment, node =>
Tools.isElementNode(node) &&
isModuleScript(node) &&
!node.attrs.some(({ name }) => name === 'src'));

Array.from(inlineModules).forEach((el, i) => {
const moduleName = `${primaryElementName}-${demoSlug.replace('.html', '')}-inline-script-${i++}.js`;
append(
fragment,
Tools.createCommentNode('playground-hide'),
Tools.createElement('script', {
type: 'module',
src: `./${demoSlug === 'index.html' ? '' : '../'}${moduleName}`,
}),
Tools.createTextNode('\n\n'),
Tools.createCommentNode('playground-hide-end'),
);

fileMap.set(`demo/${moduleName}`, {
contentType: 'application/javascript',
content: el.childNodes.map(x => x.value).join('\n'),
hidden: true,
});
});
// ENDHACK

fileMap.set(filename, {
contentType: 'text/html',
selected: isMainDemo,
content: demoPaths(serialize(fragment), demo.filePath),
label: demo.title,
});

const files = Object.fromEntries(fileMap.entries());
playgroundConfigsMap.set(primaryElementName, { files });
}
Expand Down
7 changes: 5 additions & 2 deletions docs/_includes/layout-demo.njk
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@
<link rel="stylesheet" href="{{ '/assets/base.css' | url }}">

<script type="importmap">{{ importMap | dump | safe }}</script>
<script async src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js"></script>
<script type="module">import 'element-internals-polyfill';</script>
<script async src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js"></script>
<script type="module">
import 'element-internals-polyfill';
</script>
<style>
html, body, main, [data-demo] { height: 100%; }
[data-demo] { grid-row: -1/1; }
main { display: grid; }
</style>
</head>
Expand Down
1 change: 1 addition & 0 deletions docs/_plugins/importMap.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ async function getCachedImportMap({

// TODO: automate this
Object.assign(json.imports ?? {}, {
'@rhds/tokens/': '/assets/packages/@rhds/tokens/js/',
'@rhds/elements/lib/': '/assets/packages/@rhds/elements/lib/',
'@rhds/elements/lib/context/': '/assets/packages/@rhds/elements/lib/context/',
'@rhds/elements/lib/context/color/': '/assets/packages/@rhds/elements/lib/context/color/',
Expand Down
1 change: 1 addition & 0 deletions docs/_plugins/shortcodes/playground.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ module.exports = function(eleventyConfig) {
const outdir = join(__dirname, `../../assets/playgrounds/`);
const bundle = await rollup({
input: join(__dirname, 'rh-playground.js'),
external: [/^@rhds/],
plugins: [
nodeResolve(),
importMetaAssets(),
Expand Down
61 changes: 61 additions & 0 deletions docs/_plugins/shortcodes/rh-playground.css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const style = new CSSStyleSheet();
style.replaceSync(/* css */`
:host {
position: relative;
display: block;
--_max-height: 785px;
}
::slotted(pre) {
max-height: var(--_max-height);
margin: 0 !important;
}
[hidden],
div.showing {
display: none !important;
}
div {
max-height: var(--_max-height);
overflow-y: scroll;
}
rh-button {
position: absolute;
inset-block-end: 5px;
inset-inline-end: 5px;
display: block;
}
rh-spinner {
opacity: 0;
transition: opacity 0.5s ease;
position: absolute;
inset-block-start: 50%;
inset-inline-start: 50%;
transform: translateY(-50%) translateX(-50%);
}
.loading rh-spinner {
opacity: 1;
}
.loading ::slotted(pre) {
opacity: .3;
}
playground-project {
display: block;
border: var(--rh-border-width-md, 2px) solid var(--rh-color-border-subtle-on-light, #c7c7c7);
border-radius: var(--rh-border-radius-default, 3px);
overflow: hidden;
}
playground-preview {
resize: vertical;
overflow: hidden;
}
`);
export default style;
Loading

0 comments on commit 5e64235

Please sign in to comment.