Skip to content

Commit

Permalink
Merge pull request #168 from mardanbeigi/main
Browse files Browse the repository at this point in the history
40k: Move to TSX
  • Loading branch information
rweyrauch committed Jun 16, 2024
2 parents d1f7c5d + 0635970 commit 71f541b
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 221 deletions.
2 changes: 1 addition & 1 deletion dist/prettyscribe.js

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions src/html/jsx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Inspired by https://www.meziantou.net/write-your-own-dom-element-factory-for-typescript.htm
// and https://itnext.io/lessons-learned-using-jsx-without-react-bbddb6c28561

declare global {
namespace JSX {
interface IntrinsicElements {
[elemName: string]: any;
}
}
}


export namespace PsJsx {
interface AttributeCollection {
[name: string]: string | boolean | EventListener | ((e: HTMLElement) => void);
}

export function createFragment() {
return document.createDocumentFragment();
}

export function createElement(tagName: string | Function, attributes: AttributeCollection | null, ...children: any[]): Element | DocumentFragment {
const element = typeof tagName === 'function'
? tagName() :
document.createElement(tagName);
if (attributes) {
for (const key of Object.keys(attributes)) {
const attributeValue = attributes[key];

if (typeof attributeValue === "boolean") {
element.setAttribute(key, "");
} else if (typeof attributeValue === "function") {
if (key === 'ref') {
(attributeValue as (e: HTMLElement) => void)(element);
} else if (key.startsWith("on")) {
element.addEventListener(key.substring(2), attributeValue as EventListener);
} else {
throw new Error('Unexpected function attribute');
}
} else if (key === "className") { // JSX does not allow class as a valid name
element.setAttribute("class", attributeValue);
} else {
element.setAttribute(key, attributeValue);
}
}
}

for (const child of children) {
appendChild(element, child);
}

return element;
}

function appendChild(parent: Node, child: any) {
if (typeof child === "undefined" || child === null) {
return;
}

if (Array.isArray(child)) {
for (const value of child) {
appendChild(parent, value);
}
} else if (typeof child === "string") {
parent.appendChild(document.createTextNode(child));
} else if (child instanceof Node) {
parent.appendChild(child);
} else if (typeof child === "boolean") {
// <>{condition && <a>Display when condition is true</a>}</>
// if condition is false, the child is a boolean, but we don't want to display anything
} else {
parent.appendChild(document.createTextNode(String(child)));
}
}
}
Loading

0 comments on commit 71f541b

Please sign in to comment.