@superbuilders/prompt 0.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ Copyright © 2025 Bjorn Pagen <11238136+bjornpagen@users.noreply.github.com>
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
+ purpose with or without fee is hereby granted.
5
+
6
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
7
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
8
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
9
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
10
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
11
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
12
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # @superbuilders/prompt
2
+
3
+ JSX runtime for authoring structured LLM prompts as components. Declare a per-file pragma and write prompts as composable JSX:
4
+
5
+ ```tsx
6
+ /** @jsxImportSource @superbuilders/prompt */
7
+
8
+ export function SystemPrompt(props: { role: string }) {
9
+ return (
10
+ <system>
11
+ You are {props.role}.
12
+ </system>
13
+ )
14
+ }
15
+ ```
16
+
17
+ Built for bare-Node type stripping: internal imports are `#` subpath imports resolved through the package's conditional map (`types` → `src`, `default` → `dist`), emitted per-file by tsgo with declarations and source maps.
18
+
19
+ ## Scripts
20
+
21
+ - `pnpm build` — `tsgo -p tsconfig.build.json` into `dist/`
22
+ - `pnpm typecheck` — `tsgo --noEmit`
23
+ - `pnpm lint` — `biome check .`
24
+
25
+ ## Exports
26
+
27
+ - `@superbuilders/prompt` — the component/runtime API
28
+ - `@superbuilders/prompt/jsx-runtime`, `@superbuilders/prompt/jsx-dev-runtime` — automatic-runtime entry points consumed via the `@jsxImportSource` pragma
@@ -0,0 +1,16 @@
1
+ type PromptPrimitive = string | number | boolean;
2
+ type PromptAttrValue = PromptPrimitive | null | undefined | false;
3
+ type PromptNode = PromptElement | PromptPrimitive | null | undefined | false | readonly PromptNode[];
4
+ type PromptElement = {
5
+ tag: string;
6
+ attrs: Record<string, PromptAttrValue>;
7
+ children: readonly PromptNode[];
8
+ };
9
+ type PromptComponentProps = Record<string, unknown> & {
10
+ children?: PromptNode;
11
+ };
12
+ type PromptComponent = (props: PromptComponentProps) => PromptNode;
13
+ declare function render(node: PromptNode): string;
14
+ export type { PromptAttrValue, PromptComponent, PromptComponentProps, PromptElement, PromptNode };
15
+ export { render };
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,KAAK,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAChD,KAAK,eAAe,GAAG,eAAe,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAA;AACjE,KAAK,UAAU,GAAG,aAAa,GAAG,eAAe,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,UAAU,EAAE,CAAA;AAEpG,KAAK,aAAa,GAAG;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACtC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAA;CAC/B,CAAA;AAED,KAAK,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,UAAU,CAAA;CAAE,CAAA;AAC/E,KAAK,eAAe,GAAG,CAAC,KAAK,EAAE,oBAAoB,KAAK,UAAU,CAAA;AAsFlE,iBAAS,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAQxC;AAED,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,UAAU,EAAE,CAAA;AACjG,OAAO,EAAE,MAAM,EAAE,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,87 @@
1
+ function isPromptElement(value) {
2
+ return typeof value === "object" && value !== null && "tag" in value && "attrs" in value && "children" in value;
3
+ }
4
+ function escapeText(value) {
5
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
6
+ }
7
+ function escapeAttr(value) {
8
+ return escapeText(value).replace(/"/g, "&quot;").replace(/'/g, "&apos;");
9
+ }
10
+ function renderAttrs(attrs) {
11
+ const parts = [];
12
+ for (const key in attrs) {
13
+ const value = attrs[key];
14
+ if (value === undefined || value === null || value === false) {
15
+ continue;
16
+ }
17
+ parts.push(` ${key}="${escapeAttr(String(value))}"`);
18
+ }
19
+ return parts.join("");
20
+ }
21
+ function childIsInline(node) {
22
+ if (node === undefined || node === null || node === false) {
23
+ return true;
24
+ }
25
+ if (Array.isArray(node)) {
26
+ return node.every(childIsInline);
27
+ }
28
+ return !isPromptElement(node);
29
+ }
30
+ function renderInline(node) {
31
+ if (node === undefined || node === null || node === false) {
32
+ return "";
33
+ }
34
+ if (Array.isArray(node)) {
35
+ return node.map(renderInline).join("");
36
+ }
37
+ if (isPromptElement(node)) {
38
+ return renderElement(node, 0);
39
+ }
40
+ return escapeText(String(node));
41
+ }
42
+ function renderChild(node, level) {
43
+ if (node === undefined || node === null || node === false) {
44
+ return "";
45
+ }
46
+ if (Array.isArray(node)) {
47
+ return node
48
+ .map(function renderArrayChild(child) {
49
+ return renderChild(child, level);
50
+ })
51
+ .join("");
52
+ }
53
+ if (isPromptElement(node)) {
54
+ return `${" ".repeat(level)}${renderElement(node, level)}\n`;
55
+ }
56
+ const text = escapeText(String(node));
57
+ if (text.includes("\n")) {
58
+ return `${text}\n`;
59
+ }
60
+ return `${" ".repeat(level)}${text}\n`;
61
+ }
62
+ function renderElement(element, level) {
63
+ const attrs = renderAttrs(element.attrs);
64
+ if (element.children.length === 0) {
65
+ return `<${element.tag}${attrs}></${element.tag}>`;
66
+ }
67
+ if (element.children.every(childIsInline)) {
68
+ return `<${element.tag}${attrs}>${element.children.map(renderInline).join("")}</${element.tag}>`;
69
+ }
70
+ const children = element.children
71
+ .map(function renderNestedChild(child) {
72
+ return renderChild(child, level + 1);
73
+ })
74
+ .join("");
75
+ return `<${element.tag}${attrs}>\n${children}${" ".repeat(level)}</${element.tag}>`;
76
+ }
77
+ function render(node) {
78
+ if (Array.isArray(node)) {
79
+ return node.map(render).join("\n\n");
80
+ }
81
+ if (isPromptElement(node)) {
82
+ return renderElement(node, 0);
83
+ }
84
+ return renderInline(node);
85
+ }
86
+ export { render };
87
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,SAAS,eAAe,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,UAAU,IAAI,KAAK,CAAA;AAChH,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAChC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAChF,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAChC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AACzE,CAAC;AAED,SAAS,WAAW,CAAC,KAAsC;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;QACxB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YAC9D,SAAQ;QACT,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAA;IACrD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACtB,CAAC;AAED,SAAS,aAAa,CAAC,IAAgB;IACtC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAA;IACZ,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;IACjC,CAAC;IACD,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;AAC9B,CAAC;AAED,SAAS,YAAY,CAAC,IAAgB;IACrC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3D,OAAO,EAAE,CAAA;IACV,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACvC,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IAC9B,CAAC;IACD,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AAChC,CAAC;AAED,SAAS,WAAW,CAAC,IAAgB,EAAE,KAAa;IACnD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3D,OAAO,EAAE,CAAA;IACV,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI;aACT,GAAG,CAAC,SAAS,gBAAgB,CAAC,KAAK;YACnC,OAAO,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACjC,CAAC,CAAC;aACD,IAAI,CAAC,EAAE,CAAC,CAAA;IACX,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAA;IAC9D,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IACrC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,IAAI,IAAI,CAAA;IACnB,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAA;AACxC,CAAC;AAED,SAAS,aAAa,CAAC,OAAsB,EAAE,KAAa;IAC3D,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACxC,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,OAAO,CAAC,GAAG,GAAG,KAAK,MAAM,OAAO,CAAC,GAAG,GAAG,CAAA;IACnD,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,OAAO,CAAC,GAAG,GAAG,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,GAAG,CAAA;IACjG,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ;SAC/B,GAAG,CAAC,SAAS,iBAAiB,CAAC,KAAK;QACpC,OAAO,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;IACrC,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAA;IACV,OAAO,IAAI,OAAO,CAAC,GAAG,GAAG,KAAK,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,GAAG,GAAG,CAAA;AACrF,CAAC;AAED,SAAS,MAAM,CAAC,IAAgB;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IAC9B,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAA;AAC1B,CAAC;AAGD,OAAO,EAAE,MAAM,EAAE,CAAA"}
@@ -0,0 +1,3 @@
1
+ export type { JSX } from "#jsx-runtime.ts";
2
+ export { Fragment, jsx, jsx as jsxDEV, jsxs } from "#jsx-runtime.ts";
3
+ //# sourceMappingURL=jsx-dev-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-dev-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-dev-runtime.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,MAAM,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { Fragment, jsx, jsx as jsxDEV, jsxs } from "#jsx-runtime.ts";
2
+ //# sourceMappingURL=jsx-dev-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-dev-runtime.js","sourceRoot":"","sources":["../src/jsx-dev-runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,MAAM,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,28 @@
1
+ import type { PromptComponentProps, PromptNode } from "#index.ts";
2
+ type JsxComponent<P extends PromptComponentProps = PromptComponentProps> = (props: P) => PromptNode;
3
+ declare function jsx<P extends PromptComponentProps>(tag: JsxComponent<P>, props: P): PromptNode;
4
+ declare function jsx(tag: string, props?: PromptComponentProps): PromptNode;
5
+ declare function jsxs<P extends PromptComponentProps>(tag: JsxComponent<P>, props: P): PromptNode;
6
+ declare function jsxs(tag: string, props?: PromptComponentProps): PromptNode;
7
+ declare function Fragment(props: {
8
+ children?: PromptNode;
9
+ }): PromptNode;
10
+ export declare namespace JSX {
11
+ type Element = PromptNode;
12
+ type ElementType = string | ((props: never) => PromptNode);
13
+ type ElementChildrenAttribute = {
14
+ children: unknown;
15
+ };
16
+ type IntrinsicAttributes = {
17
+ key?: string | number;
18
+ };
19
+ type IntrinsicElements = {
20
+ [tag: string]: {
21
+ children?: PromptNode;
22
+ key?: string | number;
23
+ [attr: string]: PromptNode | string | number | boolean | null | undefined;
24
+ };
25
+ };
26
+ }
27
+ export { Fragment, jsx, jsxs };
28
+ //# sourceMappingURL=jsx-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,oBAAoB,EAAiB,UAAU,EAAE,MAAM,WAAW,CAAA;AAEjG,KAAK,YAAY,CAAC,CAAC,SAAS,oBAAoB,GAAG,oBAAoB,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,UAAU,CAAA;AA0CnG,iBAAS,GAAG,CAAC,CAAC,SAAS,oBAAoB,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,UAAU,CAAA;AACxF,iBAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,oBAAoB,GAAG,UAAU,CAAA;AAiBnE,iBAAS,IAAI,CAAC,CAAC,SAAS,oBAAoB,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,UAAU,CAAA;AACzF,iBAAS,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,oBAAoB,GAAG,UAAU,CAAA;AAiBpE,iBAAS,QAAQ,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,UAAU,CAE9D;AAED,yBAAiB,GAAG,CAAC;IACpB,KAAY,OAAO,GAAG,UAAU,CAAA;IAChC,KAAY,WAAW,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,UAAU,CAAC,CAAA;IACjE,KAAY,wBAAwB,GAAG;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAA;IAC5D,KAAY,mBAAmB,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IAC3D,KAAY,iBAAiB,GAAG;QAC/B,CAAC,GAAG,EAAE,MAAM,GAAG;YACd,QAAQ,CAAC,EAAE,UAAU,CAAA;YACrB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;YACrB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;SACzE,CAAA;KACD,CAAA;CACD;AAED,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAA"}
@@ -0,0 +1,71 @@
1
+ import * as errors from "@superbuilders/errors";
2
+ /**
3
+ * Attributes must be primitives (string/number/boolean/null/undefined). A
4
+ * non-primitive attr (object, array, function) is a caller bug and THROWS —
5
+ * for a library whose whole job is "the same bytes render every run", a
6
+ * silently dropped attr would be an invisible prompt mutation.
7
+ */
8
+ function attrsFromProps(props) {
9
+ const attrs = {};
10
+ for (const key in props) {
11
+ if (key === "children" || key === "key") {
12
+ continue;
13
+ }
14
+ const value = props[key];
15
+ if (typeof value === "string" ||
16
+ typeof value === "number" ||
17
+ typeof value === "boolean" ||
18
+ value === null ||
19
+ value === undefined) {
20
+ attrs[key] = value;
21
+ continue;
22
+ }
23
+ throw errors.new(`prompt attr '${key}' must be a primitive, got ${typeof value}`);
24
+ }
25
+ return attrs;
26
+ }
27
+ function childrenFromProps(props) {
28
+ const children = props.children;
29
+ if (children === undefined) {
30
+ return [];
31
+ }
32
+ if (Array.isArray(children)) {
33
+ return children;
34
+ }
35
+ return [children];
36
+ }
37
+ function jsx(tag, props) {
38
+ let safeProps = {};
39
+ if (props !== undefined) {
40
+ safeProps = props;
41
+ }
42
+ if (typeof tag === "function") {
43
+ return tag(safeProps);
44
+ }
45
+ const element = {
46
+ tag,
47
+ attrs: attrsFromProps(safeProps),
48
+ children: childrenFromProps(safeProps)
49
+ };
50
+ return element;
51
+ }
52
+ function jsxs(tag, props) {
53
+ let safeProps = {};
54
+ if (props !== undefined) {
55
+ safeProps = props;
56
+ }
57
+ if (typeof tag === "function") {
58
+ return tag(safeProps);
59
+ }
60
+ const element = {
61
+ tag,
62
+ attrs: attrsFromProps(safeProps),
63
+ children: childrenFromProps(safeProps)
64
+ };
65
+ return element;
66
+ }
67
+ function Fragment(props) {
68
+ return props.children;
69
+ }
70
+ export { Fragment, jsx, jsxs };
71
+ //# sourceMappingURL=jsx-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.js","sourceRoot":"","sources":["../src/jsx-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAA;AAM/C;;;;;GAKG;AACH,SAAS,cAAc,CAAC,KAA2B;IAClD,MAAM,KAAK,GAAoC,EAAE,CAAA;IACjD,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;YACzC,SAAQ;QACT,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;QACxB,IACC,OAAO,KAAK,KAAK,QAAQ;YACzB,OAAO,KAAK,KAAK,QAAQ;YACzB,OAAO,KAAK,KAAK,SAAS;YAC1B,KAAK,KAAK,IAAI;YACd,KAAK,KAAK,SAAS,EAClB,CAAC;YACF,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;YAClB,SAAQ;QACT,CAAC;QACD,MAAM,MAAM,CAAC,GAAG,CAAC,gBAAgB,GAAG,8BAA8B,OAAO,KAAK,EAAE,CAAC,CAAA;IAClF,CAAC;IACD,OAAO,KAAK,CAAA;AACb,CAAC;AAED,SAAS,iBAAiB,CAAC,KAA2B;IACrD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;IAC/B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAA;IACV,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,QAAQ,CAAA;IAChB,CAAC;IACD,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClB,CAAC;AAID,SAAS,GAAG,CAAC,GAAW,EAAE,KAA4B;IACrD,IAAI,SAAS,GAAyB,EAAE,CAAA;IACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,SAAS,GAAG,KAAK,CAAA;IAClB,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,SAAS,CAAC,CAAA;IACtB,CAAC;IACD,MAAM,OAAO,GAAkB;QAC9B,GAAG;QACH,KAAK,EAAE,cAAc,CAAC,SAAS,CAAC;QAChC,QAAQ,EAAE,iBAAiB,CAAC,SAAS,CAAC;KACtC,CAAA;IACD,OAAO,OAAO,CAAA;AACf,CAAC;AAID,SAAS,IAAI,CAAC,GAAW,EAAE,KAA4B;IACtD,IAAI,SAAS,GAAyB,EAAE,CAAA;IACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,SAAS,GAAG,KAAK,CAAA;IAClB,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,SAAS,CAAC,CAAA;IACtB,CAAC;IACD,MAAM,OAAO,GAAkB;QAC9B,GAAG;QACH,KAAK,EAAE,cAAc,CAAC,SAAS,CAAC;QAChC,QAAQ,EAAE,iBAAiB,CAAC,SAAS,CAAC;KACtC,CAAA;IACD,OAAO,OAAO,CAAA;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,KAAgC;IACjD,OAAO,KAAK,CAAC,QAAQ,CAAA;AACtB,CAAC;AAgBD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAA"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@superbuilders/prompt",
3
+ "version": "0.1.0",
4
+ "description": "Tiny JSX prompt rendering primitives for Superbuilders applications",
5
+ "type": "module",
6
+ "imports": {
7
+ "#*.ts": {
8
+ "types": "./src/*.ts",
9
+ "default": "./dist/*.js"
10
+ },
11
+ "#*.tsx": {
12
+ "types": "./src/*.tsx",
13
+ "default": "./dist/*.js"
14
+ }
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ },
21
+ "./jsx-runtime": {
22
+ "types": "./dist/jsx-runtime.d.ts",
23
+ "import": "./dist/jsx-runtime.js"
24
+ },
25
+ "./jsx-dev-runtime": {
26
+ "types": "./dist/jsx-dev-runtime.d.ts",
27
+ "import": "./dist/jsx-dev-runtime.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "src"
33
+ ],
34
+ "dependencies": {
35
+ "@superbuilders/errors": "^3.0.2"
36
+ },
37
+ "devDependencies": {
38
+ "@biomejs/biome": "^2.5.2",
39
+ "@types/node": "^26.1.0",
40
+ "@typescript/native-preview": "7.0.0-dev.20260702.3",
41
+ "typescript": "^6.0.3"
42
+ },
43
+ "keywords": [
44
+ "jsx",
45
+ "prompt",
46
+ "xml",
47
+ "superbuilders"
48
+ ],
49
+ "license": "0BSD",
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "scripts": {
54
+ "build": "rm -rf dist && tsgo -p tsconfig.build.json",
55
+ "typecheck": "tsgo --noEmit",
56
+ "lint": "biome check ."
57
+ }
58
+ }
package/src/index.ts ADDED
@@ -0,0 +1,109 @@
1
+ type PromptPrimitive = string | number | boolean
2
+ type PromptAttrValue = PromptPrimitive | null | undefined | false
3
+ type PromptNode = PromptElement | PromptPrimitive | null | undefined | false | readonly PromptNode[]
4
+
5
+ type PromptElement = {
6
+ tag: string
7
+ attrs: Record<string, PromptAttrValue>
8
+ children: readonly PromptNode[]
9
+ }
10
+
11
+ type PromptComponentProps = Record<string, unknown> & { children?: PromptNode }
12
+ type PromptComponent = (props: PromptComponentProps) => PromptNode
13
+
14
+ function isPromptElement(value: unknown): value is PromptElement {
15
+ return typeof value === "object" && value !== null && "tag" in value && "attrs" in value && "children" in value
16
+ }
17
+
18
+ function escapeText(value: string): string {
19
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
20
+ }
21
+
22
+ function escapeAttr(value: string): string {
23
+ return escapeText(value).replace(/"/g, "&quot;").replace(/'/g, "&apos;")
24
+ }
25
+
26
+ function renderAttrs(attrs: Record<string, PromptAttrValue>): string {
27
+ const parts: string[] = []
28
+ for (const key in attrs) {
29
+ const value = attrs[key]
30
+ if (value === undefined || value === null || value === false) {
31
+ continue
32
+ }
33
+ parts.push(` ${key}="${escapeAttr(String(value))}"`)
34
+ }
35
+ return parts.join("")
36
+ }
37
+
38
+ function childIsInline(node: PromptNode): boolean {
39
+ if (node === undefined || node === null || node === false) {
40
+ return true
41
+ }
42
+ if (Array.isArray(node)) {
43
+ return node.every(childIsInline)
44
+ }
45
+ return !isPromptElement(node)
46
+ }
47
+
48
+ function renderInline(node: PromptNode): string {
49
+ if (node === undefined || node === null || node === false) {
50
+ return ""
51
+ }
52
+ if (Array.isArray(node)) {
53
+ return node.map(renderInline).join("")
54
+ }
55
+ if (isPromptElement(node)) {
56
+ return renderElement(node, 0)
57
+ }
58
+ return escapeText(String(node))
59
+ }
60
+
61
+ function renderChild(node: PromptNode, level: number): string {
62
+ if (node === undefined || node === null || node === false) {
63
+ return ""
64
+ }
65
+ if (Array.isArray(node)) {
66
+ return node
67
+ .map(function renderArrayChild(child) {
68
+ return renderChild(child, level)
69
+ })
70
+ .join("")
71
+ }
72
+ if (isPromptElement(node)) {
73
+ return `${" ".repeat(level)}${renderElement(node, level)}\n`
74
+ }
75
+ const text = escapeText(String(node))
76
+ if (text.includes("\n")) {
77
+ return `${text}\n`
78
+ }
79
+ return `${" ".repeat(level)}${text}\n`
80
+ }
81
+
82
+ function renderElement(element: PromptElement, level: number): string {
83
+ const attrs = renderAttrs(element.attrs)
84
+ if (element.children.length === 0) {
85
+ return `<${element.tag}${attrs}></${element.tag}>`
86
+ }
87
+ if (element.children.every(childIsInline)) {
88
+ return `<${element.tag}${attrs}>${element.children.map(renderInline).join("")}</${element.tag}>`
89
+ }
90
+ const children = element.children
91
+ .map(function renderNestedChild(child) {
92
+ return renderChild(child, level + 1)
93
+ })
94
+ .join("")
95
+ return `<${element.tag}${attrs}>\n${children}${" ".repeat(level)}</${element.tag}>`
96
+ }
97
+
98
+ function render(node: PromptNode): string {
99
+ if (Array.isArray(node)) {
100
+ return node.map(render).join("\n\n")
101
+ }
102
+ if (isPromptElement(node)) {
103
+ return renderElement(node, 0)
104
+ }
105
+ return renderInline(node)
106
+ }
107
+
108
+ export type { PromptAttrValue, PromptComponent, PromptComponentProps, PromptElement, PromptNode }
109
+ export { render }
@@ -0,0 +1,2 @@
1
+ export type { JSX } from "#jsx-runtime.ts"
2
+ export { Fragment, jsx, jsx as jsxDEV, jsxs } from "#jsx-runtime.ts"
@@ -0,0 +1,100 @@
1
+ import * as errors from "@superbuilders/errors"
2
+ import type { PromptAttrValue, PromptComponentProps, PromptElement, PromptNode } from "#index.ts"
3
+
4
+ type JsxComponent<P extends PromptComponentProps = PromptComponentProps> = (props: P) => PromptNode
5
+ type JsxTag<P extends PromptComponentProps = PromptComponentProps> = string | JsxComponent<P>
6
+
7
+ /**
8
+ * Attributes must be primitives (string/number/boolean/null/undefined). A
9
+ * non-primitive attr (object, array, function) is a caller bug and THROWS —
10
+ * for a library whose whole job is "the same bytes render every run", a
11
+ * silently dropped attr would be an invisible prompt mutation.
12
+ */
13
+ function attrsFromProps(props: PromptComponentProps): Record<string, PromptAttrValue> {
14
+ const attrs: Record<string, PromptAttrValue> = {}
15
+ for (const key in props) {
16
+ if (key === "children" || key === "key") {
17
+ continue
18
+ }
19
+ const value = props[key]
20
+ if (
21
+ typeof value === "string" ||
22
+ typeof value === "number" ||
23
+ typeof value === "boolean" ||
24
+ value === null ||
25
+ value === undefined
26
+ ) {
27
+ attrs[key] = value
28
+ continue
29
+ }
30
+ throw errors.new(`prompt attr '${key}' must be a primitive, got ${typeof value}`)
31
+ }
32
+ return attrs
33
+ }
34
+
35
+ function childrenFromProps(props: PromptComponentProps): readonly PromptNode[] {
36
+ const children = props.children
37
+ if (children === undefined) {
38
+ return []
39
+ }
40
+ if (Array.isArray(children)) {
41
+ return children
42
+ }
43
+ return [children]
44
+ }
45
+
46
+ function jsx<P extends PromptComponentProps>(tag: JsxComponent<P>, props: P): PromptNode
47
+ function jsx(tag: string, props?: PromptComponentProps): PromptNode
48
+ function jsx(tag: JsxTag, props?: PromptComponentProps): PromptNode {
49
+ let safeProps: PromptComponentProps = {}
50
+ if (props !== undefined) {
51
+ safeProps = props
52
+ }
53
+ if (typeof tag === "function") {
54
+ return tag(safeProps)
55
+ }
56
+ const element: PromptElement = {
57
+ tag,
58
+ attrs: attrsFromProps(safeProps),
59
+ children: childrenFromProps(safeProps)
60
+ }
61
+ return element
62
+ }
63
+
64
+ function jsxs<P extends PromptComponentProps>(tag: JsxComponent<P>, props: P): PromptNode
65
+ function jsxs(tag: string, props?: PromptComponentProps): PromptNode
66
+ function jsxs(tag: JsxTag, props?: PromptComponentProps): PromptNode {
67
+ let safeProps: PromptComponentProps = {}
68
+ if (props !== undefined) {
69
+ safeProps = props
70
+ }
71
+ if (typeof tag === "function") {
72
+ return tag(safeProps)
73
+ }
74
+ const element: PromptElement = {
75
+ tag,
76
+ attrs: attrsFromProps(safeProps),
77
+ children: childrenFromProps(safeProps)
78
+ }
79
+ return element
80
+ }
81
+
82
+ function Fragment(props: { children?: PromptNode }): PromptNode {
83
+ return props.children
84
+ }
85
+
86
+ export namespace JSX {
87
+ export type Element = PromptNode
88
+ export type ElementType = string | ((props: never) => PromptNode)
89
+ export type ElementChildrenAttribute = { children: unknown }
90
+ export type IntrinsicAttributes = { key?: string | number }
91
+ export type IntrinsicElements = {
92
+ [tag: string]: {
93
+ children?: PromptNode
94
+ key?: string | number
95
+ [attr: string]: PromptNode | string | number | boolean | null | undefined
96
+ }
97
+ }
98
+ }
99
+
100
+ export { Fragment, jsx, jsxs }