-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ add declarative shadow dom and docs (#18)
- Loading branch information
Showing
17 changed files
with
553 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { Meta, Title, Source } from '@storybook/blocks'; | ||
|
||
<Meta isTemplate /> | ||
|
||
<Title /> | ||
|
||
Both DEV components can be implemented via Declarative Shadow DOM using methods exported from the `devto-utils.js` file. | ||
|
||
|
||
## Server Side Rendering HTML in Node.js | ||
|
||
<Source code={` | ||
// import from npm module | ||
import { dsd } from 'profile-components/devto-utils'; | ||
const generatedTemplate = await dsd({ | ||
username: 'scottnath', | ||
},true); | ||
/** | ||
generatedTemplate contains: | ||
<template shadowrootmode="open"> | ||
<styles>(...css styles for DEV component)</styles> | ||
<section (...rest of generated HTML)</section> | ||
</template> | ||
*/ | ||
const componentHTML = \`<devto-user>\${generatedTemplate}</devto-user>\`; | ||
`} language='js' /> | ||
|
||
## Server side render in an Astro component | ||
|
||
<Source code={` | ||
--- | ||
import {dsd} from 'profile-components/devto-utils'; | ||
const declaredDOM = await dsd({ | ||
username: 'scottnath', | ||
},true) | ||
--- | ||
<devto-user | ||
data-theme="light_high_contrast" | ||
set:html={declaredDOM}> | ||
</devto-user> | ||
`} language='jsx' /> | ||
|
||
## Client side rendering via unpkg | ||
|
||
<Source code={` | ||
<!-- add empty elements to HTML --> | ||
<devto-post></devto-post> | ||
<hr /> | ||
<devto-user></devto-user> | ||
<script type="module"> | ||
// import from unpkg | ||
import { | ||
user, | ||
post, | ||
} from 'https://unpkg.com/profile-components/dist/devto-utils.js'; | ||
// post has it's own DSD method: | ||
const dsdPost = post.dsd; | ||
/** | ||
* Polyfill for Declarative Shadow DOM which, when triggered, converts | ||
* the template element into actual shadow DOM. | ||
* This is only needed when injecting _after_ page is loaded | ||
* @see https://developer.chrome.com/docs/css-ui/declarative-shadow-dom#polyfill | ||
*/ | ||
const triggerAttachShadowRoots = () => { | ||
(function attachShadowRoots(root) { | ||
root | ||
.querySelectorAll('template[shadowrootmode]') | ||
.forEach((template) => { | ||
const mode = template.getAttribute('shadowrootmode'); | ||
const shadowRoot = template.parentNode.attachShadow({ mode }); | ||
shadowRoot.appendChild(template.content); | ||
template.remove(); | ||
attachShadowRoots(shadowRoot); | ||
}); | ||
})(document); | ||
}; | ||
/** | ||
* Uses the "dsd" method to generate DSD, add the string of DSD content | ||
* to the element, then trigger the polyfill to convert the template | ||
*/ | ||
const injectDSD = async () => { | ||
const dsdHTML = await dsd({ username: 'scottnath' }, true); | ||
document.querySelector('devto-user').innerHTML = dsdHTML; | ||
// now that the HTML is async-created, the polyfill can convert it | ||
triggerAttachShadowRoots(); | ||
}; | ||
injectDSD(); | ||
/** | ||
* Uses the "dsdPost" method to generate DSD, add the string of DSD content | ||
* to the element, then trigger the polyfill to convert the template | ||
*/ | ||
const injectPostDSD = async () => { | ||
const dsdHTML = await dsdPost( | ||
{ full_name: 'scottnath/profile-components' }, | ||
true | ||
); | ||
document.querySelector('devto-post').innerHTML = dsdHTML; | ||
// now that the HTML is async-created, the polyfill can convert it | ||
triggerAttachShadowRoots(); | ||
}; | ||
injectPostDSD(); | ||
</script> | ||
`} language='html' /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
|
||
import { parseFetchedPost } from './post/content.js'; | ||
import { parseFetchedUser } from './user/content.js'; | ||
import { default as userScottnath } from './fixtures/generated/user--scottnath.json'; | ||
import { default as postProfileComponents } from './fixtures/generated/post--profile-components.json'; | ||
import { default as postDependabot } from './fixtures/generated/post--dependabot.json'; | ||
import { default as postBugfix } from './fixtures/generated/post--bugfix-multi-vite.json'; | ||
import { post, dsd } from './index.js'; | ||
import docs from './dsd.docs.mdx'; | ||
|
||
|
||
export default { | ||
title: 'DevTo/Declarative Shadow DOM', | ||
parameters: { | ||
docs: { | ||
page: docs | ||
}, | ||
}, | ||
tags: ['autodocs'], | ||
decorators: [(story) => `${story()} | ||
<script> | ||
(function attachShadowRoots(root) { | ||
root.querySelectorAll("template[shadowrootmode]").forEach(template => { | ||
const mode = template.getAttribute("shadowrootmode"); | ||
const shadowRoot = template.parentNode.attachShadow({ mode }); | ||
shadowRoot.appendChild(template.content); | ||
template.remove(); | ||
attachShadowRoots(shadowRoot); | ||
}); | ||
})(document); | ||
</script> | ||
`], | ||
}; | ||
|
||
export const Post = { | ||
loaders: [ | ||
async ({args}) => ({ | ||
dsdOutput: await (await post.dsd(args)), | ||
}), | ||
], | ||
render: (args, { loaded: { dsdOutput } }) => { | ||
return ` | ||
<devto-post-dsd>${dsdOutput}</devto-post-dsd> | ||
`; | ||
}, | ||
args: { | ||
...parseFetchedPost(postProfileComponents) | ||
}, | ||
} | ||
|
||
export const User = { | ||
loaders: [ | ||
async ({args}) => ({ | ||
dsdOutput: await (await dsd(args)), | ||
}), | ||
], | ||
render: (args, { loaded: { dsdOutput } }) => { | ||
return ` | ||
<devto-user-dsd data-theme="dark">${dsdOutput}</devto-user-dsd> | ||
`; | ||
}, | ||
args: { | ||
...parseFetchedUser(userScottnath), | ||
latest_post: stringify(parseFetchedPost(postDependabot)), | ||
popular_post: stringify(parseFetchedPost(postBugfix)), | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.