Comparing version 1.0.1 to 2.0.0
@@ -5,9 +5,9 @@ "use strict"; | ||
const attributeToHtmlTagString = ([key, value]) => { | ||
if (value === undefined || value === true) { | ||
if (value === true) { | ||
return `${key}`; | ||
} | ||
if (value === false) { | ||
if (value === false || value === null || value === undefined) { | ||
return ""; | ||
} | ||
return `${key}="${value?.toString().replace(/"/g, """)}"`; | ||
return `${key}="${value.toString().replace(/"/g, """)}"`; | ||
}; | ||
@@ -14,0 +14,0 @@ exports.attributeToHtmlTagString = attributeToHtmlTagString; |
@@ -1,2 +0,1 @@ | ||
import type { JSXTagElem } from "../../jsx/jsx.types"; | ||
import type { HTMLElementStruct, RendererHTMLAttributes } from "../types"; | ||
@@ -6,5 +5,5 @@ export declare class HTMLElementResolver { | ||
constructor(attributeMap: Record<string, string>); | ||
resolveAttributes(element: JSXTagElem): RendererHTMLAttributes; | ||
resolveChildren(element: JSXTagElem): JSX.Element[]; | ||
resolveElement(element: JSXTagElem): HTMLElementStruct; | ||
resolveAttributes(element: JSXTE.TagElement): RendererHTMLAttributes; | ||
resolveChildren(element: JSXTE.TagElement): JSX.Element[]; | ||
resolveElement(element: JSXTE.TagElement): HTMLElementStruct; | ||
} |
@@ -1,3 +0,2 @@ | ||
import type { JSXTagElem } from "../jsx/jsx.types"; | ||
import type { HTMLElementStruct } from "./types"; | ||
export declare const getHTMLStruct: (element: JSXTagElem, attributeMap: Record<string, string>) => HTMLElementStruct; | ||
export declare const getHTMLStruct: (element: JSXTE.TagElement, attributeMap: Record<string, string>) => HTMLElementStruct; |
@@ -28,3 +28,8 @@ "use strict"; | ||
for (const child of htmlStruct.children) { | ||
results.push((0, exports.jsxElemToHtmlSync)(child, { indent: indent + 2, attributeMap })); | ||
const renderedChild = (0, exports.jsxElemToHtmlSync)(child, { | ||
indent: indent + 2, | ||
attributeMap, | ||
}); | ||
if (renderedChild.length > 0) | ||
results.push(renderedChild); | ||
} | ||
@@ -42,3 +47,8 @@ return results.join("\n"); | ||
for (const child of htmlStruct.children) { | ||
children.push((0, exports.jsxElemToHtmlSync)(child, { indent: indent + 2, attributeMap })); | ||
const renderedChild = (0, exports.jsxElemToHtmlSync)(child, { | ||
indent: indent + 2, | ||
attributeMap, | ||
}); | ||
if (renderedChild.length > 0) | ||
children.push(renderedChild); | ||
} | ||
@@ -67,3 +77,8 @@ return [startTag, ...children, endTag].join("\n"); | ||
for (const child of htmlStruct.children) { | ||
results.push(await (0, exports.jsxElemToHtmlAsync)(child, { indent: indent + 2, attributeMap })); | ||
const renderedChild = await (0, exports.jsxElemToHtmlAsync)(child, { | ||
indent: indent + 2, | ||
attributeMap, | ||
}); | ||
if (renderedChild.length > 0) | ||
results.push(renderedChild); | ||
} | ||
@@ -81,3 +96,8 @@ return results.join("\n"); | ||
for (const child of htmlStruct.children) { | ||
children.push(await (0, exports.jsxElemToHtmlAsync)(child, { indent: indent + 2, attributeMap })); | ||
const renderedChild = await (0, exports.jsxElemToHtmlAsync)(child, { | ||
indent: indent + 2, | ||
attributeMap, | ||
}); | ||
if (renderedChild.length > 0) | ||
children.push(renderedChild); | ||
} | ||
@@ -84,0 +104,0 @@ return [startTag, ...children, endTag].join("\n"); |
import type { Rewrap } from "../html-parser/types"; | ||
export declare type AttributeBool = true | false | "true" | "false"; | ||
export declare type BaseHTMLTagProps = { | ||
children?: JSX.ElementChildren; | ||
accesskey?: string; | ||
class?: string; | ||
contenteditable?: AttributeBool; | ||
dir?: "ltr" | "rtl" | "auto"; | ||
draggable?: AttributeBool | "auto"; | ||
hidden?: AttributeBool; | ||
id?: string; | ||
lang?: string; | ||
onabort?: string; | ||
onafterprint?: string; | ||
onbeforeprint?: string; | ||
onbeforeunload?: string; | ||
onblur?: string; | ||
oncanplay?: string; | ||
oncanplaythrough?: string; | ||
onchange?: string; | ||
onclick?: string; | ||
oncontextmenu?: string; | ||
oncopy?: string; | ||
oncuechange?: string; | ||
oncut?: string; | ||
ondblclick?: string; | ||
ondrag?: string; | ||
ondragend?: string; | ||
ondragenter?: string; | ||
ondragleave?: string; | ||
ondragover?: string; | ||
ondragstart?: string; | ||
ondrop?: string; | ||
ondurationchange?: string; | ||
onemptied?: string; | ||
onended?: string; | ||
onerror?: string; | ||
onfocus?: string; | ||
onhashchange?: string; | ||
oninput?: string; | ||
oninvalid?: string; | ||
onkeydown?: string; | ||
onkeypress?: string; | ||
onkeyup?: string; | ||
onload?: string; | ||
onloadeddata?: string; | ||
onloadedmetadata?: string; | ||
onloadstart?: string; | ||
onmousedown?: string; | ||
onmousemove?: string; | ||
onmouseout?: string; | ||
onmouseover?: string; | ||
onmouseup?: string; | ||
onmousewheel?: string; | ||
onoffline?: string; | ||
ononline?: string; | ||
onpagehide?: string; | ||
onpageshow?: string; | ||
onpaste?: string; | ||
onpause?: string; | ||
onplay?: string; | ||
onplaying?: string; | ||
onpopstate?: string; | ||
onprogress?: string; | ||
onratechange?: string; | ||
onreset?: string; | ||
onresize?: string; | ||
onscroll?: string; | ||
onsearch?: string; | ||
onseeked?: string; | ||
onseeking?: string; | ||
onselect?: string; | ||
onstalled?: string; | ||
onstorage?: string; | ||
onsubmit?: string; | ||
onsuspend?: string; | ||
ontimeupdate?: string; | ||
ontoggle?: string; | ||
onunload?: string; | ||
onvolumechange?: string; | ||
onwaiting?: string; | ||
onwheel?: string; | ||
slot?: string; | ||
spellcheck?: AttributeBool; | ||
style?: string; | ||
tabindex?: string | number; | ||
title?: string; | ||
translate?: "yes" | "no"; | ||
}; | ||
export declare type HTMLProps<T extends object = never> = Rewrap<ExtendBaseProps<[ | ||
T | ||
] extends [never] ? BaseHTMLTagProps : Partial<T> & BaseHTMLTagProps>>; | ||
] extends [never] ? JSXTE.BaseHTMLTagProps : Partial<T> & JSXTE.BaseHTMLTagProps>>; | ||
declare type ExtendBaseProps<P> = { | ||
[K in keyof P]: TJSXExtends.AttributeAcceptedTypes extends { | ||
[K in keyof P]: JSXTE.AttributeAcceptedTypes extends { | ||
[E in K]: infer T; | ||
@@ -99,7 +12,116 @@ } ? T | P[K] : P[K]; | ||
declare global { | ||
namespace TJSXExtends { | ||
namespace JSXTE { | ||
interface AttributeAcceptedTypes { | ||
} | ||
type TagElement = { | ||
type: "tag"; | ||
tag: string | ((props: ElementProps) => Element) | ((props: ElementProps) => Promise<Element>); | ||
props: ElementProps; | ||
}; | ||
type TextNodeElement = { | ||
type: "textNode"; | ||
text: string; | ||
}; | ||
type SyncElement = TagElement | TextNodeElement; | ||
type ElementChildren = JSX.Element | string | number | Array<JSX.Element | string | number | Array<JSX.Element | string | number>>; | ||
type ElementProps = { | ||
children?: ElementChildren; | ||
[k: string]: any; | ||
}; | ||
type PropsWithChildren<P extends object> = P & { | ||
children?: JSXTE.ElementChildren; | ||
}; | ||
type Component<P extends object = {}> = (props: PropsWithChildren<P>) => JSX.Element; | ||
type AsyncComponent<P extends object = {}> = (props: PropsWithChildren<P>) => Promise<JSX.Element>; | ||
interface BaseHTMLTagProps { | ||
children?: ElementChildren; | ||
accesskey?: string; | ||
class?: string; | ||
contenteditable?: AttributeBool; | ||
dir?: "ltr" | "rtl" | "auto"; | ||
draggable?: AttributeBool | "auto"; | ||
hidden?: AttributeBool; | ||
id?: string; | ||
inert?: AttributeBool; | ||
lang?: string; | ||
onabort?: string; | ||
onafterprint?: string; | ||
onbeforeprint?: string; | ||
onbeforeunload?: string; | ||
onblur?: string; | ||
oncanplay?: string; | ||
oncanplaythrough?: string; | ||
onchange?: string; | ||
onclick?: string; | ||
oncontextmenu?: string; | ||
oncopy?: string; | ||
oncuechange?: string; | ||
oncut?: string; | ||
ondblclick?: string; | ||
ondrag?: string; | ||
ondragend?: string; | ||
ondragenter?: string; | ||
ondragleave?: string; | ||
ondragover?: string; | ||
ondragstart?: string; | ||
ondrop?: string; | ||
ondurationchange?: string; | ||
onemptied?: string; | ||
onended?: string; | ||
onerror?: string; | ||
onfocus?: string; | ||
onhashchange?: string; | ||
oninput?: string; | ||
oninvalid?: string; | ||
onkeydown?: string; | ||
onkeypress?: string; | ||
onkeyup?: string; | ||
onload?: string; | ||
onloadeddata?: string; | ||
onloadedmetadata?: string; | ||
onloadstart?: string; | ||
onmousedown?: string; | ||
onmousemove?: string; | ||
onmouseout?: string; | ||
onmouseover?: string; | ||
onmouseup?: string; | ||
onmousewheel?: string; | ||
onoffline?: string; | ||
ononline?: string; | ||
onpagehide?: string; | ||
onpageshow?: string; | ||
onpaste?: string; | ||
onpause?: string; | ||
onplay?: string; | ||
onplaying?: string; | ||
onpopstate?: string; | ||
onprogress?: string; | ||
onratechange?: string; | ||
onreset?: string; | ||
onresize?: string; | ||
onscroll?: string; | ||
onsearch?: string; | ||
onseeked?: string; | ||
onseeking?: string; | ||
onselect?: string; | ||
onstalled?: string; | ||
onstorage?: string; | ||
onsubmit?: string; | ||
onsuspend?: string; | ||
ontimeupdate?: string; | ||
ontoggle?: string; | ||
onunload?: string; | ||
onvolumechange?: string; | ||
onwaiting?: string; | ||
onwheel?: string; | ||
role?: string; | ||
slot?: string; | ||
spellcheck?: AttributeBool; | ||
style?: string; | ||
tabindex?: string | number; | ||
title?: string; | ||
translate?: "yes" | "no"; | ||
} | ||
} | ||
} | ||
export {}; |
declare type CreateElementProps = { | ||
[k: string]: any; | ||
children?: JSX.ElementChildren; | ||
children?: JSXTE.ElementChildren; | ||
}; | ||
@@ -5,0 +5,0 @@ export declare const createElement: (tag: string | ((props: any) => JSX.Element) | ((props: any) => Promise<JSX.Element>), props?: CreateElementProps | undefined, ...children: Array<JSX.Element | string | number | Array<JSX.Element | string | number>>) => JSX.Element; |
@@ -28,3 +28,8 @@ "use strict"; | ||
props.children = props.children.map((child) => { | ||
if (typeof child === "string") { | ||
if (typeof child === "boolean" || | ||
child === null || | ||
child === undefined) { | ||
return { type: "tag", tag: exports.Fragment, props: {} }; | ||
} | ||
else if (typeof child === "string") { | ||
return { type: "textNode", text: child }; | ||
@@ -38,2 +43,7 @@ } | ||
} | ||
else if (typeof props.children === "boolean" || | ||
props.children === null || | ||
props.children === undefined) { | ||
props.children = []; | ||
} | ||
} | ||
@@ -40,0 +50,0 @@ return { |
@@ -48,25 +48,5 @@ import type { HTMLProps } from "./base-html-tag-props"; | ||
import type { VideoTagProps } from "./prop-types/video-jsx-props"; | ||
export declare type JSXTagElem = { | ||
type: "tag"; | ||
tag: string | ((props: JSX.ElementProps) => Element) | ((props: JSX.ElementProps) => Promise<Element>); | ||
props: JSX.ElementProps; | ||
}; | ||
export declare type JSXTextNodeElem = { | ||
type: "textNode"; | ||
text: string; | ||
}; | ||
export declare type JSXSyncElem = JSXTagElem | JSXTextNodeElem; | ||
declare global { | ||
namespace JSX { | ||
type PropsWithChildren<P extends object> = P & { | ||
children?: JSX.ElementChildren; | ||
}; | ||
type Component<P extends object = {}> = (props: PropsWithChildren<P>) => JSX.Element; | ||
type AsyncComponent<P extends object = {}> = (props: PropsWithChildren<P>) => Promise<JSX.Element>; | ||
type ElementChildren = JSX.Element | string | number | Array<JSX.Element | string | number | Array<JSX.Element | string | number>>; | ||
type ElementProps = { | ||
children?: ElementChildren; | ||
[k: string]: any; | ||
}; | ||
type Element = JSXTagElem | JSXTextNodeElem | Promise<JSXTagElem | JSXTextNodeElem>; | ||
type Element = JSXTE.TagElement | JSXTE.TextNodeElement | Promise<JSXTE.TagElement | JSXTE.TextNodeElement>; | ||
type LibraryManagedAttributes<T, PropsWithChildren> = PropsWithChildren; | ||
@@ -73,0 +53,0 @@ interface IntrinsicElements { |
@@ -1,3 +0,2 @@ | ||
import type { JSXTagElem } from "../jsx/jsx.types"; | ||
export declare const resolveElement: (element: JSXTagElem) => { | ||
export declare const resolveElement: (element: JSXTE.TagElement) => { | ||
attributes: { | ||
@@ -4,0 +3,0 @@ [k: string]: any; |
@@ -9,3 +9,3 @@ { | ||
"eslint": "^8.15.0", | ||
"git-hook-tasks": "ncpa0cpl/git-hook-tasks", | ||
"git-hook-tasks": "github:ncpa0cpl/git-hook-tasks", | ||
"husky": "^8.0.1", | ||
@@ -19,6 +19,6 @@ "jest": "^28.1.0", | ||
"name": "jsxte", | ||
"version": "1.0.1", | ||
"version": "2.0.0", | ||
"main": "./dist/index.js", | ||
"scripts": { | ||
"build": "rm -rf ./dist && tsc", | ||
"build": "rm -rf ./dist && tsc -p tsconfig.build.json", | ||
"test:lint": "eslint .", | ||
@@ -25,0 +25,0 @@ "test:tsc": "tsc --noEmit", |
@@ -20,2 +20,4 @@ # JSX Template Engine | ||
(See example configurations [here](./docs/config-examples/)). | ||
Once you are done with that you can start writing your templates and rendering them. | ||
@@ -105,2 +107,45 @@ | ||
## Extending the typings | ||
JSXTE should be able to parse any html attributes you put in, as well as custom web component tags, although you may see type errors if you use anything that is not defined in the library typings. If you wish to use them it is recommended you extend the typings to disable said errors. | ||
### Adding custom web component tags | ||
To add a typing for a custom web component simply add a declare block in one of your project `.ts` or `.tsx` files, like this one: | ||
```tsx | ||
declare global { | ||
namespace JSX { | ||
interface IntrinsicElements { | ||
"my-custom-web-component": { | ||
/* here include the attributes your component can take */ | ||
"data-example-attribute"?: string; | ||
}; | ||
} | ||
} | ||
} | ||
// with it it's possible to use this without type errors: | ||
const MyComponent = () => ( | ||
<my-custom-web-component data-example-attribute="Hello"></my-custom-web-component> | ||
); | ||
``` | ||
### Adding a global html attribute | ||
There is a dictionary of html attributes that are available for every default html tag, that dictionary can be extended like so: | ||
```tsx | ||
declare global { | ||
namespace JSXTE { | ||
interface BaseHTMLTagProps { | ||
"new-attribute"?: string; | ||
} | ||
} | ||
} | ||
// with it it's possible to use this without type errors: | ||
const MyComponent = () => <div new-attribute="Hello"></div>; | ||
``` | ||
## Express JS View Engine | ||
@@ -107,0 +152,0 @@ |
@@ -7,3 +7,3 @@ { | ||
"outDir": "./dist", | ||
"rootDir": "./src", | ||
"rootDirs": ["./src", "./__tests__"], | ||
"downlevelIteration": true, | ||
@@ -15,5 +15,8 @@ "strict": true, | ||
"skipLibCheck": true, | ||
"forceConsistentCasingInFileNames": true | ||
"forceConsistentCasingInFileNames": true, | ||
"jsx": "react", | ||
"jsxFactory": "jsx", | ||
"jsxFragmentFactory": "Fragment" | ||
}, | ||
"include": ["src/**/*"] | ||
"include": ["src/**/*", "__tests__/**/*"] | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
65176
150
1399
222
0