Skip to content

Commit

Permalink
fix: removed auto kebab and improved jsdocs (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurfiorette committed Sep 14, 2023
1 parent c3b3c01 commit e067851
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 98 deletions.
30 changes: 15 additions & 15 deletions benchmark.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Benchmark

- 2023-09-14T20:06:09.655Z
- 2023-09-14T21:20:07.035Z
- Node: v18.15.0
- V8: 10.2.154.26-node.25
- OS: linux
Expand All @@ -10,30 +10,30 @@

| Runs | @kitajs/html | typed-html | + | .compile() | + / @kitajs/html | + / typed-html |
| ------ | ------------ | ---------- | ----- | ---------- | ---------------- | -------------- |
| 10 | 0.0088ms | 0.0177ms | 2.02x | 0.0066ms | 1.33x | 2.68x |
| 10000 | 0.9501ms | 3.2714ms | 3.44x | 0.6968ms | 1.36x | 4.7x |
| 100000 | 12.2114ms | 19.6453ms | 1.61x | 2.7776ms | 4.4x | 7.07x |
| 10 | 0.0094ms | 0.0164ms | 1.74x | 0.0038ms | 2.5x | 4.34x |
| 10000 | 1.1723ms | 2.9252ms | 2.5x | 1.278ms | 0.92x | 2.29x |
| 100000 | 8.8428ms | 20.1493ms | 2.28x | 2.7031ms | 3.27x | 7.45x |

## Many Props

| Runs | @kitajs/html | typed-html | + | .compile() | + / @kitajs/html | + / typed-html |
| ------ | ------------ | ------------ | ----- | ---------- | ---------------- | -------------- |
| 10 | 0.2479ms | 1.3757ms | 5.55x | 0.0031ms | 79.8x | 442.91x |
| 10000 | 240.6256ms | 982.6665ms | 4.08x | 0.7723ms | 311.56x | 1272.37x |
| 100000 | 2436.4599ms | 10844.2049ms | 4.45x | 4.4179ms | 551.49x | 2454.59x |
| Runs | @kitajs/html | typed-html | + | .compile() | + / @kitajs/html | + / typed-html |
| ------ | ------------ | ---------- | ----- | ---------- | ---------------- | -------------- |
| 10 | 0.1971ms | 1.3064ms | 6.63x | 0.0036ms | 54.09x | 358.62x |
| 10000 | 166.2978ms | 938.6489ms | 5.64x | 0.9456ms | 175.87x | 992.66x |
| 100000 | 1693.7948ms | 8952.945ms | 5.29x | 4.292ms | 394.64x | 2085.96x |

## Many Components

| Runs | @kitajs/html | typed-html | + | .compile() | + / @kitajs/html | + / typed-html |
| ------ | ------------ | ----------- | ----- | ---------- | ---------------- | -------------- |
| 10 | 0.2174ms | 0.5805ms | 2.67x | 0.0058ms | 37.43x | 99.91x |
| 10000 | 169.6069ms | 665.6724ms | 3.92x | 1.5865ms | 106.91x | 419.6x |
| 100000 | 1747.2244ms | 5227.3891ms | 2.99x | 7.5666ms | 230.91x | 690.85x |
| 10 | 0.2237ms | 0.7488ms | 3.35x | 0.0072ms | 31.14x | 104.22x |
| 10000 | 171.0714ms | 500.6814ms | 2.93x | 1.449ms | 118.06x | 345.53x |
| 100000 | 1818.6258ms | 5277.3456ms | 2.9x | 9.2505ms | 196.6x | 570.49x |

## Big Component

| Runs | @kitajs/html | typed-html | + | .compile() | + / @kitajs/html | + / typed-html |
| ------ | ------------ | ----------- | ----- | ---------- | ---------------- | -------------- |
| 10 | 0.2235ms | 0.8053ms | 3.6x | 0.0048ms | 46.53x | 167.64x |
| 10000 | 175.1073ms | 735.6298ms | 4.2x | 0.9891ms | 177.03x | 743.7x |
| 100000 | 1841.2463ms | 7872.5854ms | 4.28x | 5.1064ms | 360.58x | 1541.72x |
| 10 | 0.5231ms | 0.9827ms | 1.88x | 0.0059ms | 88.03x | 165.38x |
| 10000 | 131.2238ms | 829.1856ms | 6.32x | 0.9444ms | 138.95x | 878x |
| 100000 | 1346.2388ms | 7372.6771ms | 5.48x | 4.6654ms | 288.56x | 1580.29x |
40 changes: 22 additions & 18 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,29 @@
declare namespace Html {
/**
* A const used to represent a html fragment.
*
*/
export const Fragment: unique symbol

/**
* Escapes a string for safe use as HTML text content.
* Returns true if the character at the given index is an uppercase character.
*
* @param {string} input the string to check.
* @param {number} index the index of the character to check.
* @returns {boolean} if the character at the given index is an uppercase character.
* @this {void}
*/
export function isUpper(this: void, input: string, index: number): boolean

/**
* Escapes a string for safe use as HTML text content. If the value is not a string,
* it is coerced to one with its own `toString()` method.
*
* @param {unknown} value the value to escape. If the value is not a string it will be converted to a string with `toString()` or `toISOString()` if it is a Date.
* @param {unknown} value the value to escape.
* @returns {string} the escaped string.
* @this {void}
*/
export function escapeHtml(this: void, value: unknown): string
export function escapeHtml(this: void, value: any): string

/**
* Returns true if the element is a html void element.
Expand All @@ -41,7 +53,7 @@ declare namespace Html {
* @returns {string} the generated html style string.
* @this {void}
*/
export function styleToString(this: void, style: object | string): boolean
export function styleToString(this: void, style: object | string): string

/**
* Transforms an object of attributes into a html attributes string.
Expand All @@ -64,16 +76,6 @@ declare namespace Html {
*/
export function toKebabCase(this: void, camel: string): string

/**
* Returns true if the character at the given index is an uppercase character.
*
* @param {string} input the string to check.
* @param {number} index the index of the character to check.
* @returns {boolean} if the character at the given index is an uppercase character.
* @this {void}
*/
export function isUpper(this: void, input: string, index: number): boolean

/**
* Generates a html string from the given contents.
*
Expand All @@ -93,15 +95,17 @@ declare namespace Html {
/**
* Joins raw string html elements into a single html string.
*
* A raw html fragment is just an array of strings, this method concatenates.
* A raw html fragment is just an array of strings, this method concatenates .
*
* @param {(string | string[])[]} contents an maybe nested array of strings to concatenate.
* @returns {string} the concatenated string of contents.
* @param {import('.').Children[]} contents an maybe nested array of strings to concatenate.
* @param {boolean} [escape=false] if we should escape the contents before concatenating them.
* @returns {string} the concatenated and escaped string of contents.
* @this {void}
*/
export function contentsToString(
this: void,
contents: (string | string[])[]
contents: Children[],
escape?: boolean
): JSX.Element

/**
Expand Down
76 changes: 17 additions & 59 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,20 @@ const ESCAPED_REGEX = /[<"'&]/
const CAMEL_REGEX = /[a-z][A-Z]/

/**
* A const used to represent a html fragment.
*
* @typedef {import('.').Fragment}
* @type {typeof import('.').Fragment}
*/
const Fragment = Symbol.for('kHtmlFragment')

/**
* Returns true if the character at the given index is an uppercase character.
*
* @param {string} input the string to check.
* @param {number} index the index of the character to check.
* @returns {boolean} if the character at the given index is an uppercase character.
* @this {void}
* @type {import('.').isUpper}
*/
function isUpper (input, index) {
const code = input.charCodeAt(index)
return code >= 65 /* A */ && code <= 90 /* Z */
}

/**
* Converts a camel cased string to a kebab cased string.
*
* @param {string} camel the camel cased string to convert.
* @this {void}
* @type {import('.').toKebabCase}
*/
function toKebabCase (camel) {
// This is a optimization to avoid the whole conversion process when the
Expand Down Expand Up @@ -66,11 +56,7 @@ function toKebabCase (camel) {
}

/**
* Escapes a string to avoid any possible harmful html from being executed.
*
* @param {any} value the value to escape.
* @returns {string} the escaped string.
* @this {void}
* @type {import('.').escapeHtml}
*/
function escapeHtml (value) {
if (typeof value !== 'string') {
Expand Down Expand Up @@ -122,11 +108,7 @@ function escapeHtml (value) {
}

/**
* Returns true if the element is a html void element.
*
* @param {string} tag the name of the element to check.
* @returns {boolean} if the element is a html void element.
* @this {void}
* @type {import('.').isVoidElement}
*/
function isVoidElement (tag) {
// Ordered by most common to least common.
Expand All @@ -151,11 +133,7 @@ function isVoidElement (tag) {
}

/**
* Transforms an object of style attributes into a html style string.
*
* @param {object | string} style
* @returns {string}
* @this {void}
* @type {import('.').styleToString}
*/
function styleToString (style) {
// Faster escaping process that only looks for the " character.
Expand Down Expand Up @@ -244,14 +222,7 @@ function styleToString (style) {
}

/**
* Transforms an object of attributes into a html attributes string.
*
*
* @example `a b="c" d="1"`
*
* @param {object} attributes a record of literal values to use as attributes.
* @returns {string} the generated html attributes string.
* @this {void}
* @type {import('.').attributesToString}
*/
function attributesToString (attributes) {
if (!attributes) {
Expand Down Expand Up @@ -296,8 +267,7 @@ function attributesToString (attributes) {
if (type === 'boolean') {
// Only add the attribute if the value is true.
if (value) {
// @ts-expect-error - this indexing is safe.
result += ' ' + toKebabCase(key)
result += ' ' + key
}

continue
Expand All @@ -307,8 +277,7 @@ function attributesToString (attributes) {
continue
}

// @ts-expect-error - this indexing is safe.
result += ' ' + toKebabCase(key)
result += ' ' + key

if (type !== 'string') {
// Non objects are
Expand Down Expand Up @@ -358,14 +327,7 @@ function attributesToString (attributes) {
}

/**
* Joins raw string html elements into a single html string.
*
* A raw html fragment is just an array of strings, this method concatenates .
*
* @param {import('.').Children[]} contents an maybe nested array of strings to concatenate.
* @param {boolean} [escape=false] if we should escape the contents before concatenating them.
* @returns {string} the concatenated and escaped string of contents.
* @this {void}
* @type {import('.').contentsToString}
*/
function contentsToString (contents, escape) {
const length = contents.length
Expand Down Expand Up @@ -399,13 +361,10 @@ function contentsToString (contents, escape) {
}

/**
* Generates a html string from the given contents.
* Just to stop TS from complaining about the type.
* @param {any} name
*
* @param {string | Function | typeof Fragment} name the name of the element to create or a function that creates the element.
* @param {import('.').PropsWithChildren<any> | null} attrs a record of literal values to use as attributes. A property named `children` will be used as the children of the element.
* @param {...import('.').Children} children the inner contents of the element.
* @returns {string} the generated html string.
* @this {void}
* @type {import('.').createElement}
*/
function createElement (name, attrs, ...children) {
// Adds the children to the attributes if it is not present.
Expand Down Expand Up @@ -455,12 +414,10 @@ function createElement (name, attrs, ...children) {
}

/**
* Compiles html with the given arguments specified with $name syntax.
* Just to stop TS from complaining about the type.
* @returns {Function}
*
* @param {(proxy: any) => string} htmlFn
* @param {boolean} [strict=true] if we should throw an error when a property is not found.
* @returns {function} the compiled template function
* @this {void}
* @type {import('.').compile}
*/
function compile (htmlFn, strict = true, separator = '/*\x00*/') {
if (typeof htmlFn !== 'function') {
Expand All @@ -470,6 +427,7 @@ function compile (htmlFn, strict = true, separator = '/*\x00*/') {
const properties = new Set()

const html = htmlFn(
//@ts-expect-error - this proxy will meet the props with children requirements.
new Proxy(
{},
{
Expand Down
6 changes: 3 additions & 3 deletions jsx.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ declare namespace JSX {
safe?: undefined | boolean

/**
* Included here to work as a drop-in replacement
* Included here to work as a react drop-in replacement
*
* @deprecated please use `class`.
*/
Expand Down Expand Up @@ -164,7 +164,7 @@ declare namespace JSX {
}

interface HtmlFormTag extends HtmlTag {
acceptCharset?: undefined | string
['accept-charset']?: undefined | string
action?: undefined | string
autocomplete?: undefined | string
enctype?: undefined | string
Expand Down Expand Up @@ -270,7 +270,7 @@ declare namespace JSX {

interface HtmlMetaTag extends HtmlTag {
name?: undefined | string
httpEquiv?: undefined | string
['http-equiv']?: undefined | string
content?: undefined | string
charset?: undefined | string
}
Expand Down
6 changes: 4 additions & 2 deletions test/simple-html.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ test('simple html structures', () => {
})

test('untyped & unknown attributes', () => {
assert.equal(<a notHref></a>, '<a not-href></a>')
assert.equal(<c notHref></c>, '<c not-href></c>')
assert.equal(<a not-href></a>, '<a not-href></a>')
assert.equal(<c not-href></c>, '<c not-href></c>')
assert.equal(<c notHref></c>, '<c notHref></c>')
assert.equal(<c notHref></c>, '<c notHref></c>')

function D() {
return <div />
Expand Down
3 changes: 2 additions & 1 deletion test/style.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ test('style property', () => {
<div style={{ backgroundColor: 'red' }}></div>
<div style="background-color: blue;"></div>
<div style="background-color:green;"></div>
<div style="backgroundColor:green;"></div>
</>,
'<div style="background-color:red;"></div><div style="background-color: blue;"></div><div style="background-color:green;"></div>'
'<div style="background-color:red;"></div><div style="background-color: blue;"></div><div style="background-color:green;"></div><div style="backgroundColor:green;"></div>'
)
})

0 comments on commit e067851

Please sign in to comment.