feat: code-block component & sample code

This commit is contained in:
Ayo 2023-10-19 15:57:39 +02:00
parent d12f6a5aa6
commit 9225fa662e
7 changed files with 80 additions and 9 deletions

3
public/prism.css Normal file
View file

@ -0,0 +1,3 @@
/* PrismJS 1.29.0
https://prismjs.com/download.html#themes=prism&languages=clike+javascript */
code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}

5
public/prism.js Normal file

File diff suppressed because one or more lines are too long

View file

@ -62,6 +62,8 @@ async function insertRegistry(
key.replace(`.${type}`, "") key.replace(`.${type}`, "")
); );
console.log(">>> availableComponents", availableComponents);
const usedCustomElements = []; const usedCustomElements = [];
walkSync(ast, (node) => { walkSync(ast, (node) => {
@ -74,6 +76,7 @@ async function insertRegistry(
// insert registry script to head // insert registry script to head
if (usedCustomElements.length > 0) { if (usedCustomElements.length > 0) {
console.log(">>> usedCustomElements", usedCustomElements);
const registryScript = await buildRegistry(usedCustomElements, type); const registryScript = await buildRegistry(usedCustomElements, type);
walkSync(ast, (node) => { walkSync(ast, (node) => {
if (node.type === ELEMENT_NODE && node.name === "head") { if (node.type === ELEMENT_NODE && node.name === "head") {
@ -95,7 +98,9 @@ import { WebComponent } from "https://unpkg.com/web-component-base@1.6.15/WebCom
`assets:components:${name}.${type}` `assets:components:${name}.${type}`
); );
registryScript += content; registryScript += content;
const evalStore = eval(`class WebComponent {};(${content.toString()})`); const evalStore = eval(
`class WebComponent {}; class HTMLElement {}; (${content.toString()})`
);
const className = new evalStore().constructor.name; const className = new evalStore().constructor.name;
registryScript += `customElements.define("${name}", ${className});`; registryScript += `customElements.define("${name}", ${className});`;
@ -224,13 +229,31 @@ async function useFragments(html: string) {
); );
if (node.type === ELEMENT_NODE && !!usedFragment) { if (node.type === ELEMENT_NODE && !!usedFragment) {
node.children.push(parse(usedFragment.text)); const value = replaceSlots(usedFragment.text, node);
node.children.push(parse(value));
} }
}); });
return render(ast); return render(ast);
} }
function replaceSlots(text: string, sourceNode: UltraNode) {
const regex = /<slot \/>/g;
var match;
while ((match = regex.exec(text))) {
let [key, _value] = match;
const slotName = sourceNode.attributes.slot;
const h = sourceNode.children.find((node) => node.name === slotName);
if (h) {
text = text?.replace(key, h.value);
sourceNode.children.splice(sourceNode.children.indexOf(h), 1);
}
}
return text;
}
async function getFiles(type: string) { async function getFiles(type: string) {
return (await useStorage().getKeys("assets:components")) return (await useStorage().getKeys("assets:components"))
.map((key) => key.replace("assets:components:", "")) .map((key) => key.replace("assets:components:", ""))

View file

@ -0,0 +1,20 @@
class CodeBlockComponent extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
let lang = this.classList.value;
lang = lang.replace("language-", "");
const trimmed = this.innerHTML.trim();
const template = `
<div>
<pre class="${this.classList}" id="pre"><code id="code">${trimmed}</code></pre>
</div>
`;
this.innerHTML = template;
}
}

View file

@ -1,5 +1,4 @@
class HelloWorld extends WebComponent { class HelloWorld extends WebComponent {
name = "";
static properties = ["name"]; static properties = ["name"];
onInit() { onInit() {

View file

@ -1,6 +1,9 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>McFly: Back to the Basics. Into the Future.</title> <title>McFly: Back to the Basics. Into the Future.</title>
<link rel="stylesheet" href="./reset.css"></style> <link rel="stylesheet" href="./reset.css" />
</head> <link rel="stylesheet" href="./prism.css" />
<script src="./prism.js"></script>
<slot />
</head>

View file

@ -12,6 +12,24 @@
Here's a sample interactive custom element: Here's a sample interactive custom element:
<hello-world name="McFly"></hello-world> <hello-world name="McFly"></hello-world>
</p> </p>
<code-block class="language-js line-numbers" data-line="2">
<pre>
class HelloWorld extends WebComponent {
static properties = ["name"];
onInit() {
let count = 0;
this.onclick = () => {
this.setAttribute("name", `Clicked ${++count}x`);
};
}
get template() {
return `<button style="cursor:pointer">Hello ${this.name}!</button>`;
}
}
</pre>
</code-block>
<p> <p>
Start at the very basic of writing HTML files and enhance with standard Start at the very basic of writing HTML files and enhance with standard
web technologies or go advanced as you like, at your own pace. web technologies or go advanced as you like, at your own pace.