@mpen/jsxhtml 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- import type { AnyAttributes } from '../jsx-types';
1
+ import type { HtmlAttributes } from '../htmlspec/elements';
2
2
  /**
3
3
  * `<!DOCTYPE html><html ...>{children}</html>`
4
4
  */
5
- export declare function HtmlDocument({ children, ...htmlAttrs }: AnyAttributes): import("src/jsx-runtime").JSX.Element;
5
+ export declare function HtmlDocument({ children, ...htmlAttrs }: HtmlAttributes): import("src/jsx-runtime").JSX.Element;
@@ -2,5 +2,6 @@ import { JsxRawHtml } from '../jsx-elements';
2
2
  import type { StringChildren } from '../jsx-types';
3
3
  /**
4
4
  * Unescaped HTML.
5
+ * @experimental
5
6
  */
6
7
  export declare function RawHtml({ children }: StringChildren): JsxRawHtml;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env -S bun test
2
+ export {};
@@ -15,8 +15,14 @@ export interface AudioAttributes extends CommonAttributes<ElementForTag<'audio'>
15
15
  controlslist?: 'anonymous' | 'use-credentials';
16
16
  /**
17
17
  * The **`crossorigin`** attribute, valid on the audio, img, link, script, and video elements, provides support for CORS, defining how the element handles cross-origin requests, thereby enabling the configuration of the CORS requests for the element's fetched data. Depending on the element, the attribute can be a CORS settings attribute.
18
+ *
19
+ * Possible values:
20
+ * - `anonymous`: Request uses CORS headers with credentials mode set to `same-origin` (no credentials sent for cross-origin requests).
21
+ * - `use-credentials`: Request uses CORS headers with credentials mode set to `include` (credentials always sent).
22
+ * - `""`: Setting the attribute to an empty value (or providing it without a value) is the same as `anonymous`.
23
+ * - `true`: Boolean form; emits the attribute without a value (same as `""` / `anonymous`).
18
24
  */
19
- crossorigin?: 'anonymous' | 'use-credentials';
25
+ crossorigin?: '' | 'anonymous' | 'use-credentials' | true;
20
26
  /**
21
27
  * A Boolean attribute used to disable the capability of remote playback in devices that are attached using wired (HDMI, DVI, etc.) and wireless technologies (Miracast, Chromecast, DLNA, AirPlay, etc.). See the proposed Remote Playback API specification for more information. In Safari, you can use `x-webkit-airplay="deny"` as a fallback.
22
28
  */
@@ -8,8 +8,14 @@ export interface ImgAttributes extends CommonAttributes<ElementForTag<'img'>> {
8
8
  alt?: string;
9
9
  /**
10
10
  * The **`crossorigin`** attribute, valid on the audio, img, link, script, and video elements, provides support for CORS, defining how the element handles cross-origin requests, thereby enabling the configuration of the CORS requests for the element's fetched data. Depending on the element, the attribute can be a CORS settings attribute.
11
+ *
12
+ * Possible values:
13
+ * - `anonymous`: Request uses CORS headers with credentials mode set to `same-origin` (no credentials sent for cross-origin requests).
14
+ * - `use-credentials`: Request uses CORS headers with credentials mode set to `include` (credentials always sent).
15
+ * - `""`: Setting the attribute to an empty value (or providing it without a value) is the same as `anonymous`.
16
+ * - `true`: Boolean form; emits the attribute without a value (same as `""` / `anonymous`).
11
17
  */
12
- crossorigin?: 'anonymous' | 'use-credentials';
18
+ crossorigin?: '' | 'anonymous' | 'use-credentials' | true;
13
19
  /**
14
20
  * This attribute provides a hint to the browser as to whether it should perform image decoding along with rendering the other DOM content in a single presentation step that looks more "correct" (`sync`), or render and present the other DOM content first and then decode the image and present it later (`async`). In practice, `async` means that the next paint does not wait for the image to decode. It is often difficult to perceive any noticeable effect when using `decoding` on static `<img ` elements. They'll likely be initially rendered as empty images while the image files are fetched (either from the network or from the cache) and then handled independently anyway, so the "syncing" of content updates is less apparent. However, the blocking of rendering while decoding happens, while often quite small, _can_ be measured - even if it is difficult to observe with the human eye. See What does the image decoding attribute actually do? for a more detailed analysis (tunetheweb.com, 2023). Using different `decoding` types can result in more noticeable differences when dynamically inserting `<img ` elements into the DOM via JavaScript - see HTMLImageElement.decoding for more details. Allowed values: Decode the image synchronously along with rendering the other DOM content, and present everything together. Decode the image asynchronously, after rendering and presenting the other DOM content. No preference for the decoding mode; the browser decides what is best for the user. This is the default value.
15
21
  *
@@ -14,8 +14,14 @@ export interface LinkAttributes extends CommonAttributes<ElementForTag<'link'>>
14
14
  blocking?: 'render';
15
15
  /**
16
16
  * The **`crossorigin`** attribute, valid on the audio, img, link, script, and video elements, provides support for CORS, defining how the element handles cross-origin requests, thereby enabling the configuration of the CORS requests for the element's fetched data. Depending on the element, the attribute can be a CORS settings attribute.
17
+ *
18
+ * Possible values:
19
+ * - `anonymous`: Request uses CORS headers with credentials mode set to `same-origin` (no credentials sent for cross-origin requests).
20
+ * - `use-credentials`: Request uses CORS headers with credentials mode set to `include` (credentials always sent).
21
+ * - `""`: Setting the attribute to an empty value (or providing it without a value) is the same as `anonymous`.
22
+ * - `true`: Boolean form; emits the attribute without a value (same as `""` / `anonymous`).
17
23
  */
18
- crossorigin?: 'anonymous' | 'use-credentials';
24
+ crossorigin?: '' | 'anonymous' | 'use-credentials' | true;
19
25
  /**
20
26
  * The Boolean **`disabled`** attribute, when present, makes the element not mutable, focusable, or even submitted with the form. The user can neither edit nor focus on the control, nor its form control descendants.
21
27
  */
@@ -67,9 +73,10 @@ export interface LinkAttributes extends CommonAttributes<ElementForTag<'link'>>
67
73
  * This attribute defines the sizes of the icons for visual media contained in the resource. It must be present only if the `rel` contains a value of `icon` or a non-standard type such as Apple's `apple-touch-icon`. It may have the following values:
68
74
  *
69
75
  * Possible values:
70
- * - any
76
+ * - any (the icon can be scaled to any size, such as a vector format like `image/svg+xml`)
77
+ * - A whitespace-separated list of sizes, each in the format `<width>x<height>` or `<width>X<height>` in pixels
71
78
  */
72
- sizes?: 'any';
79
+ sizes?: 'any' | string;
73
80
  /**
74
81
  * This attribute is used to define the type of the content linked to. The value of the attribute should be a MIME type such as **text/html**, **text/css**, and so on. The common use of this attribute is to define the type of stylesheet being referenced (such as **text/css**), but given that CSS is the only stylesheet language used on the web, not only is it possible to omit the `type` attribute, but is actually now recommended practice. It is also used on `rel="preload"` link types, to make sure the browser only downloads file types that it supports.
75
82
  */
@@ -19,8 +19,14 @@ export interface ScriptAttributes extends CommonAttributes<ElementForTag<'script
19
19
  blocking?: 'render';
20
20
  /**
21
21
  * The **`crossorigin`** attribute, valid on the audio, img, link, script, and video elements, provides support for CORS, defining how the element handles cross-origin requests, thereby enabling the configuration of the CORS requests for the element's fetched data. Depending on the element, the attribute can be a CORS settings attribute.
22
+ *
23
+ * Possible values:
24
+ * - `anonymous`: Request uses CORS headers with credentials mode set to `same-origin` (no credentials sent for cross-origin requests).
25
+ * - `use-credentials`: Request uses CORS headers with credentials mode set to `include` (credentials always sent).
26
+ * - `""`: Setting the attribute to an empty value (or providing it without a value) is the same as `anonymous`.
27
+ * - `true`: Boolean form; emits the attribute without a value (same as `""` / `anonymous`).
22
28
  */
23
- crossorigin?: '' | 'anonymous' | 'use-credentials';
29
+ crossorigin?: '' | 'anonymous' | 'use-credentials' | true;
24
30
  /**
25
31
  * This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded event. Scripts with the `defer` attribute will prevent the `DOMContentLoaded` event from firing until the script has loaded and finished evaluating. Scripts with the `defer` attribute will execute in the order in which they appear in the document. This attribute allows the elimination of **parser-blocking JavaScript** where the browser would have to load and evaluate scripts before continuing to parse. `async` has a similar effect in this case. If the attribute is specified with the `async` attribute, the element will act as if only the `async` attribute is specified.
26
32
  */
@@ -16,8 +16,14 @@ export interface VideoAttributes extends CommonAttributes<ElementForTag<'video'>
16
16
  controlslist?: 'anonymous' | 'use-credentials';
17
17
  /**
18
18
  * The **`crossorigin`** attribute, valid on the audio, img, link, script, and video elements, provides support for CORS, defining how the element handles cross-origin requests, thereby enabling the configuration of the CORS requests for the element's fetched data. Depending on the element, the attribute can be a CORS settings attribute.
19
+ *
20
+ * Possible values:
21
+ * - `anonymous`: Request uses CORS headers with credentials mode set to `same-origin` (no credentials sent for cross-origin requests).
22
+ * - `use-credentials`: Request uses CORS headers with credentials mode set to `include` (credentials always sent).
23
+ * - `""`: Setting the attribute to an empty value (or providing it without a value) is the same as `anonymous`.
24
+ * - `true`: Boolean form; emits the attribute without a value (same as `""` / `anonymous`).
19
25
  */
20
- crossorigin?: 'anonymous' | 'use-credentials';
26
+ crossorigin?: '' | 'anonymous' | 'use-credentials' | true;
21
27
  /**
22
28
  * Prevents the browser from suggesting a Picture-in-Picture context menu or to request Picture-in-Picture automatically in some cases.
23
29
  */
package/dist/index.cjs CHANGED
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
 
7
- var jsxRuntime = require("./jsx-runtime-BQPDXeiv.js");
7
+ var jsxRuntime = require("./jsx-runtime-hI3DpKLL.js");
8
8
 
9
9
  function C({children}) {
10
10
  {
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { E as EMPTY, j as jsx, J as JsxDocType, a as jsxs, F as Fragment, b as JsxRawHtml, f as flattenString, i as isJsxNode } from "./jsx-runtime-DlHYwToA.js";
1
+ import { E as EMPTY, j as jsx, J as JsxDocType, a as jsxs, F as Fragment, b as JsxRawHtml, f as flattenString, i as isJsxNode } from "./jsx-runtime-VLGtunVG.js";
2
2
 
3
- export { e as JsxComment, d as JsxElement, g as JsxEmpty, h as JsxFragment, k as JsxNode, c as js } from "./jsx-runtime-DlHYwToA.js";
3
+ export { e as JsxComment, d as JsxElement, g as JsxEmpty, h as JsxFragment, k as JsxNode, c as js } from "./jsx-runtime-VLGtunVG.js";
4
4
 
5
5
  function C({children}) {
6
6
  {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- var jsxRuntime = require("./jsx-runtime-BQPDXeiv.js");
3
+ var jsxRuntime = require("./jsx-runtime-hI3DpKLL.js");
4
4
 
5
5
  function jsxDEV(tag, props, key, isStaticChildren, source, self) {
6
6
  let node = jsxRuntime.jsx(...arguments);
@@ -1,6 +1,6 @@
1
- import { j as jsx, l as isJsxComponent, e as JsxComment, h as JsxFragment } from "./jsx-runtime-DlHYwToA.js";
1
+ import { j as jsx, l as isJsxComponent, e as JsxComment, h as JsxFragment } from "./jsx-runtime-VLGtunVG.js";
2
2
 
3
- export { F as Fragment, m as JSX } from "./jsx-runtime-DlHYwToA.js";
3
+ export { F as Fragment, m as JSX } from "./jsx-runtime-VLGtunVG.js";
4
4
 
5
5
  function jsxDEV(tag, props, key, isStaticChildren, source, self) {
6
6
  let node = jsx(...arguments);
@@ -1363,10 +1363,6 @@ function isObjectLike(obj) {
1363
1363
  return typeof obj === "object" && obj !== null;
1364
1364
  }
1365
1365
 
1366
- function isObject$1(obj) {
1367
- return obj != null && (typeof obj === "object" || typeof obj === "function");
1368
- }
1369
-
1370
1366
  function isPlainObject(obj) {
1371
1367
  if (obj == null || Object.prototype.toString.call(obj) !== "[object Object]") return false;
1372
1368
  const proto = Object.getPrototypeOf(obj);
@@ -1443,32 +1439,44 @@ function attrValue(value) {
1443
1439
  if (isFunction$1(value)) {
1444
1440
  value = `(${value}).call(this,event)`;
1445
1441
  }
1446
- return `"${String(value).replace(/"/gu, entity)}"`;
1442
+ const stringValue = String(value);
1443
+ const needsQuoted = stringValue.length === 0 || /[ \t\n\f\r"'=<>`]/u.test(stringValue);
1444
+ if (!needsQuoted) return stringValue;
1445
+ if (!stringValue.includes('"')) {
1446
+ return `"${stringValue.replace(/"/gu, entity)}"`;
1447
+ }
1448
+ if (!stringValue.includes("'")) {
1449
+ return `'${stringValue.replace(/'/gu, entity)}'`;
1450
+ }
1451
+ return `"${stringValue.replace(/"/gu, entity)}"`;
1447
1452
  }
1448
1453
 
1449
1454
  function attrKvPair(rawAttr, rawVal) {
1450
- let escAttr = attrName(rawAttr);
1451
- if (/^data-/.test(rawAttr) && !isString$1(rawVal)) {
1452
- rawVal = JSON.stringify(rawVal);
1453
- }
1454
1455
  if (rawVal === true) {
1455
- return escAttr;
1456
+ return attrName(rawAttr);
1456
1457
  }
1457
1458
  if (rawVal === false || rawVal == null) {
1458
1459
  return null;
1459
1460
  }
1460
- if (rawAttr === "class" && !isString$1(rawVal)) {
1461
- rawVal = classCat(rawVal);
1462
- }
1463
- if (rawAttr === "style" && isPlainObject(rawVal)) {
1464
- rawVal = styleObjectToString(rawVal);
1461
+ if (rawAttr === "class") {
1462
+ if (!isString$1(rawVal)) {
1463
+ rawVal = classCat(rawVal);
1464
+ }
1465
+ } else if (rawAttr === "style") {
1466
+ if (isPlainObject(rawVal)) {
1467
+ rawVal = styleObjectToString(rawVal);
1468
+ }
1469
+ } else if (rawAttr.startsWith("data-")) {
1470
+ if (!isString$1(rawVal)) {
1471
+ rawVal = JSON.stringify(rawVal);
1472
+ }
1465
1473
  }
1466
- return `${escAttr}=${attrValue(rawVal)}`;
1474
+ return `${attrName(rawAttr)}=${attrValue(rawVal)}`;
1467
1475
  }
1468
1476
 
1469
1477
  function attrs(attributes) {
1470
1478
  if (attributes == null) return "";
1471
- if (isObject$1(attributes)) {
1479
+ if (isPlainObject(attributes)) {
1472
1480
  attributes = Object.entries(attributes);
1473
1481
  }
1474
1482
  return attributes.map((([k, v]) => attrKvPair(k, v))).filter((x => x)).map((x => ` ${x}`)).join("");
@@ -1365,10 +1365,6 @@ function isObjectLike(obj) {
1365
1365
  return typeof obj === "object" && obj !== null;
1366
1366
  }
1367
1367
 
1368
- function isObject$1(obj) {
1369
- return obj != null && (typeof obj === "object" || typeof obj === "function");
1370
- }
1371
-
1372
1368
  function isPlainObject(obj) {
1373
1369
  if (obj == null || Object.prototype.toString.call(obj) !== "[object Object]") return false;
1374
1370
  const proto = Object.getPrototypeOf(obj);
@@ -1445,32 +1441,44 @@ function attrValue(value) {
1445
1441
  if (isFunction$1(value)) {
1446
1442
  value = `(${value}).call(this,event)`;
1447
1443
  }
1448
- return `"${String(value).replace(/"/gu, entity)}"`;
1444
+ const stringValue = String(value);
1445
+ const needsQuoted = stringValue.length === 0 || /[ \t\n\f\r"'=<>`]/u.test(stringValue);
1446
+ if (!needsQuoted) return stringValue;
1447
+ if (!stringValue.includes('"')) {
1448
+ return `"${stringValue.replace(/"/gu, entity)}"`;
1449
+ }
1450
+ if (!stringValue.includes("'")) {
1451
+ return `'${stringValue.replace(/'/gu, entity)}'`;
1452
+ }
1453
+ return `"${stringValue.replace(/"/gu, entity)}"`;
1449
1454
  }
1450
1455
 
1451
1456
  function attrKvPair(rawAttr, rawVal) {
1452
- let escAttr = attrName(rawAttr);
1453
- if (/^data-/.test(rawAttr) && !isString$1(rawVal)) {
1454
- rawVal = JSON.stringify(rawVal);
1455
- }
1456
1457
  if (rawVal === true) {
1457
- return escAttr;
1458
+ return attrName(rawAttr);
1458
1459
  }
1459
1460
  if (rawVal === false || rawVal == null) {
1460
1461
  return null;
1461
1462
  }
1462
- if (rawAttr === "class" && !isString$1(rawVal)) {
1463
- rawVal = classCat(rawVal);
1464
- }
1465
- if (rawAttr === "style" && isPlainObject(rawVal)) {
1466
- rawVal = styleObjectToString(rawVal);
1463
+ if (rawAttr === "class") {
1464
+ if (!isString$1(rawVal)) {
1465
+ rawVal = classCat(rawVal);
1466
+ }
1467
+ } else if (rawAttr === "style") {
1468
+ if (isPlainObject(rawVal)) {
1469
+ rawVal = styleObjectToString(rawVal);
1470
+ }
1471
+ } else if (rawAttr.startsWith("data-")) {
1472
+ if (!isString$1(rawVal)) {
1473
+ rawVal = JSON.stringify(rawVal);
1474
+ }
1467
1475
  }
1468
- return `${escAttr}=${attrValue(rawVal)}`;
1476
+ return `${attrName(rawAttr)}=${attrValue(rawVal)}`;
1469
1477
  }
1470
1478
 
1471
1479
  function attrs(attributes) {
1472
1480
  if (attributes == null) return "";
1473
- if (isObject$1(attributes)) {
1481
+ if (isPlainObject(attributes)) {
1474
1482
  attributes = Object.entries(attributes);
1475
1483
  }
1476
1484
  return attributes.map((([k, v]) => attrKvPair(k, v))).filter((x => x)).map((x => ` ${x}`)).join("");
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- var jsxRuntime = require("./jsx-runtime-BQPDXeiv.js");
3
+ var jsxRuntime = require("./jsx-runtime-hI3DpKLL.js");
4
4
 
5
5
  exports.Fragment = jsxRuntime.Fragment;
6
6
 
@@ -1 +1 @@
1
- export { F as Fragment, m as JSX, j as jsx, a as jsxs } from "./jsx-runtime-DlHYwToA.js";
1
+ export { F as Fragment, m as JSX, j as jsx, a as jsxs } from "./jsx-runtime-VLGtunVG.js";
@@ -5,6 +5,9 @@ export type PlainObject = Record<PropertyKey, unknown>;
5
5
  export type { ClassNames, StyleObject, AttributeValue, AttrKvPair, AttrArr, AttrObj, Attributes };
6
6
  export type UnkFn = (...args: unknown[]) => unknown;
7
7
  export type AnyFn = (...args: any[]) => any;
8
+ /**
9
+ * @experimental
10
+ */
8
11
  export type HtmlSafe = {
9
12
  __html: string;
10
13
  };
package/dist/render.d.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  import type { HtmlSafe, JsxRenderable } from './jsx-types';
2
+ /**
3
+ * @experimental
4
+ */
2
5
  export declare function isHtmlSafe(x: any): x is HtmlSafe;
3
6
  export declare function render(el: JsxRenderable): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpen/jsxhtml",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "packageManager": "bun@1.3.7",
5
5
  "exports": {
6
6
  ".": {