@spirobel/mininext 0.7.5 → 0.8.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/README.md +4 -18
- package/dist/backend/html.d.ts +46 -0
- package/dist/backend/html.js +233 -0
- package/dist/backend/miniresolve.d.ts +8 -0
- package/dist/backend/miniresolve.js +60 -0
- package/dist/frontend/minidom.d.ts +8 -0
- package/dist/frontend/minidom.js +29 -0
- package/dist/frontend/minirender.d.ts +10 -0
- package/dist/frontend/minirender.js +136 -0
- package/dist/frontend/miniresolve.d.ts +9 -0
- package/dist/frontend/miniresolve.js +143 -0
- package/dist/frontend/minirouter.d.ts +18 -0
- package/dist/frontend/minirouter.js +107 -0
- package/dist/minicache.d.ts +26 -0
- package/dist/minicache.js +44 -0
- package/dist/mininext.d.ts +41 -22
- package/dist/mininext.js +127 -229
- package/package.json +2 -2
- package/dist/html.d.ts +0 -73
- package/dist/html.js +0 -288
- package/dist/url.d.ts +0 -289
- package/dist/url.js +0 -546
package/dist/mininext.js
CHANGED
|
@@ -1,242 +1,140 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { state } from "./minicache";
|
|
2
|
+
import { resolve } from "./frontend/miniresolve";
|
|
3
|
+
import { resolve as backendResolve } from "./backend/miniresolve";
|
|
4
|
+
import { build, getCallerDir, newBackendMini, renderBackend, } from "./backend/html";
|
|
5
|
+
export { renderRoot } from "./frontend/minidom";
|
|
6
|
+
export { createRouter } from "./frontend/minirouter";
|
|
7
|
+
export const isBackend = typeof window === "undefined";
|
|
8
|
+
export function html(stringLiterals, ...values) {
|
|
9
|
+
return constructMiniHtmlString(stringLiterals, values);
|
|
8
10
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
await devServer();
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
const streamPlugin = {
|
|
21
|
-
name: "node stream in the frontend",
|
|
22
|
-
setup(build) {
|
|
23
|
-
build.onResolve({ filter: /^stream$/ }, (args) => {
|
|
24
|
-
const path_to_stream_lib = path.resolve(projectRoot(), "node_modules/stream-browserify/index.js");
|
|
25
|
-
if (path_to_stream_lib)
|
|
26
|
-
return {
|
|
27
|
-
path: path_to_stream_lib,
|
|
28
|
-
};
|
|
29
|
-
});
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
const bufferPlugin = {
|
|
33
|
-
name: "node buffer in the frontend",
|
|
34
|
-
setup(build) {
|
|
35
|
-
build.onResolve({ filter: /^buffer$/ }, (args) => {
|
|
36
|
-
const path_to_buffer_lib = path.resolve(projectRoot(), "node_modules/buffer/index.js");
|
|
37
|
-
if (path_to_buffer_lib)
|
|
38
|
-
return {
|
|
39
|
-
path: path_to_buffer_lib,
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
const cryptoPlugin = {
|
|
45
|
-
name: "node crypto in the frontend",
|
|
46
|
-
setup(build) {
|
|
47
|
-
build.onResolve({ filter: /^crypto$/ }, (args) => {
|
|
48
|
-
const path_to_crypto_lib = path.resolve(projectRoot(), "node_modules/crypto-browserify/index.js");
|
|
49
|
-
if (path_to_crypto_lib)
|
|
50
|
-
return {
|
|
51
|
-
path: path_to_crypto_lib,
|
|
52
|
-
};
|
|
53
|
-
});
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
const nodeHttpsPlugin = {
|
|
57
|
-
name: "node https in the frontend",
|
|
58
|
-
setup(build) {
|
|
59
|
-
build.onResolve({ filter: /^https$/ }, (args) => {
|
|
60
|
-
const path_to_node_https_lib = path.resolve(projectRoot(), "node_modules/https-browserify/index.js");
|
|
61
|
-
if (path_to_node_https_lib)
|
|
62
|
-
return {
|
|
63
|
-
path: path_to_node_https_lib,
|
|
64
|
-
};
|
|
65
|
-
});
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
async function buildBackend(backendPath = "backend/backend.ts") {
|
|
69
|
-
global.bundledFrontends = {};
|
|
70
|
-
global.bundledSVGs = {};
|
|
71
|
-
const i = await import(path.resolve(projectRoot(), backendPath));
|
|
72
|
-
for (const frontend of url.getFrontends()) {
|
|
73
|
-
const firstPlaceToLook = path.resolve(path.dirname(frontend.callerPath), `frontend/${frontend.frontendFilePath}`);
|
|
74
|
-
const secondPlaceToLook = path.resolve(projectRoot(), `frontend/${frontend.frontendFilePath}`);
|
|
75
|
-
const frontEndPath = (await Bun.file(firstPlaceToLook).exists())
|
|
76
|
-
? firstPlaceToLook
|
|
77
|
-
: secondPlaceToLook;
|
|
78
|
-
try {
|
|
79
|
-
const frontendResult = await $ `bun run build.ts frontend ${frontEndPath}`.json();
|
|
80
|
-
bundledFrontends[`/${frontendResult.url}`] = {
|
|
81
|
-
frontendContent: frontendResult.script,
|
|
82
|
-
frontendFilePath: frontend.frontendFilePath,
|
|
83
|
-
position: frontend.position,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
if (error &&
|
|
88
|
-
typeof error === "object" &&
|
|
89
|
-
"exitCode" in error &&
|
|
90
|
-
"stdout" in error &&
|
|
91
|
-
"stderr" in error &&
|
|
92
|
-
error.stdout instanceof Buffer &&
|
|
93
|
-
error.stderr instanceof Buffer) {
|
|
94
|
-
console.error(`Failed with exit code: ${error.exitCode}`);
|
|
95
|
-
console.error("Standard Output:", error.stdout.toString());
|
|
96
|
-
console.error("Standard Error:", error.stderr.toString());
|
|
97
|
-
}
|
|
98
|
-
console.log(await $ `bun run build.ts frontend ${frontEndPath}`.text());
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
for (const svg of url.getSvgs()) {
|
|
102
|
-
const firstPlaceToLook = path.resolve(path.dirname(svg.callerPath), `svgs/${svg.svgFilePath}`);
|
|
103
|
-
const secondPlaceToLook = path.resolve(projectRoot(), `${svg.svgFilePath}`);
|
|
104
|
-
const svgResolvedFilePath = (await Bun.file(firstPlaceToLook).exists())
|
|
105
|
-
? firstPlaceToLook
|
|
106
|
-
: secondPlaceToLook;
|
|
107
|
-
const parsedSvgPath = path.parse(svgResolvedFilePath);
|
|
108
|
-
const svgContent = Bun.file(svgResolvedFilePath);
|
|
109
|
-
const svgHash = Bun.hash(await svgContent.arrayBuffer());
|
|
110
|
-
const svgUrl = `/${parsedSvgPath.name}-${svgHash}.svg`;
|
|
111
|
-
bundledSVGs[svgUrl] = {
|
|
112
|
-
svgContent: await svgContent.text(),
|
|
113
|
-
svgFilePath: svg.svgFilePath,
|
|
114
|
-
position: svg.position,
|
|
115
|
-
options: svg.options,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
const res = await Bun.build({
|
|
119
|
-
entrypoints: [path.resolve(projectRoot(), backendPath)],
|
|
120
|
-
outdir: path.resolve(projectRoot(), "dist"),
|
|
121
|
-
naming: "backend.js",
|
|
122
|
-
minify: Bun.argv[2] === "dev" ? false : true, //production
|
|
123
|
-
target: "bun",
|
|
124
|
-
define: {
|
|
125
|
-
bundledFrontends: JSON.stringify(bundledFrontends),
|
|
126
|
-
bundledSVGs: JSON.stringify(bundledSVGs),
|
|
11
|
+
export function constructMiniHtmlString(stringLiterals, values) {
|
|
12
|
+
return {
|
|
13
|
+
stringLiterals,
|
|
14
|
+
values,
|
|
15
|
+
resolve: (mini) => {
|
|
16
|
+
if (isBackend)
|
|
17
|
+
return backendResolve(stringLiterals, values, mini);
|
|
18
|
+
return resolve(stringLiterals, values, mini);
|
|
127
19
|
},
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
console.log(result);
|
|
141
|
-
const url = path.basename(result.outputs[0].path);
|
|
142
|
-
//results.push({ file, p });
|
|
143
|
-
return { url, script: await result.outputs[0].text() };
|
|
20
|
+
async build(mini, root, config) {
|
|
21
|
+
if (!root)
|
|
22
|
+
root = getCallerDir();
|
|
23
|
+
return await build({ stringLiterals, values, root, mini, config });
|
|
24
|
+
},
|
|
25
|
+
renderBackend: (mini) => {
|
|
26
|
+
if (!mini)
|
|
27
|
+
mini = newBackendMini();
|
|
28
|
+
backendResolve(stringLiterals, values, mini);
|
|
29
|
+
return renderBackend(mini.cacheAndCursor).result;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
144
32
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const success = server.upgrade(request);
|
|
153
|
-
return success
|
|
154
|
-
? new Response("Reloader works!")
|
|
155
|
-
: new Response("Reloader WebSocket upgrade error", { status: 400 });
|
|
33
|
+
export function makeNewMini(cac) {
|
|
34
|
+
return {
|
|
35
|
+
html,
|
|
36
|
+
state: (name, value, global) => {
|
|
37
|
+
if (isBackend)
|
|
38
|
+
global = true;
|
|
39
|
+
return state(name, value, cac, global);
|
|
156
40
|
},
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
ws.send("Reload!");
|
|
162
|
-
refreshed_once = true;
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
message(ws, message) { }, // a message is received
|
|
41
|
+
flatten,
|
|
42
|
+
cacheAndCursor: cac,
|
|
43
|
+
fill: (...args) => {
|
|
44
|
+
throw new Error("this method can only be used if the mini instance was made from a html skeleton, const skeleton = html`<div></div>`.build(); const mini = skeleton.mini(); const htmlresult = skeleton.fill(...args);");
|
|
166
45
|
},
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function standardFlattenRoot(htmlstrings) {
|
|
49
|
+
return html `<div>${htmlstrings}</div>`;
|
|
50
|
+
}
|
|
51
|
+
export function flatten(htmlStringArray, flattenRootFn = standardFlattenRoot) {
|
|
52
|
+
const flattenedArray = combineMiniHtmlStrings(htmlStringArray);
|
|
53
|
+
return flattenValues(flattenRootFn(flattenedArray));
|
|
54
|
+
}
|
|
55
|
+
export function flattenValues(miniHtmlString) {
|
|
56
|
+
const literalsArray = [];
|
|
57
|
+
const values = [];
|
|
58
|
+
let mergeWithPrior = false;
|
|
59
|
+
let index = 0;
|
|
60
|
+
for (const literal of miniHtmlString.stringLiterals) {
|
|
61
|
+
if (mergeWithPrior) {
|
|
62
|
+
mergeWithPrior = false;
|
|
63
|
+
literalsArray[index] += literal;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
literalsArray.push(literal);
|
|
180
67
|
}
|
|
181
|
-
|
|
182
|
-
|
|
68
|
+
const value = miniHtmlString.values[index];
|
|
69
|
+
if (typeof value === "function") {
|
|
70
|
+
throw new Error(`resolve components before passing them into the root element when flattening,
|
|
71
|
+
with const miniHtmlString = component(mini);
|
|
72
|
+
|
|
73
|
+
optimally just have the root element's only value be the htmlstringsarray
|
|
74
|
+
you want to flatten. This is not the place for complex logic,
|
|
75
|
+
it is just to wrap your array in an <ul>, <ol> or <div> element.
|
|
76
|
+
|
|
77
|
+
(every mini html string needs to have only one root element)`);
|
|
78
|
+
}
|
|
79
|
+
else if (value && typeof value === "object" && "resolve" in value) {
|
|
80
|
+
const priorLiteral = literalsArray[index];
|
|
81
|
+
if (!priorLiteral)
|
|
82
|
+
throw new Error("no prior literal, ");
|
|
83
|
+
literalsArray[index] = priorLiteral + value.stringLiterals[0];
|
|
84
|
+
literalsArray.push(...value.stringLiterals.slice(1));
|
|
85
|
+
mergeWithPrior = true;
|
|
86
|
+
values.push(...value.values);
|
|
87
|
+
index += value.stringLiterals.slice(1).length;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
if (typeof value === "string" || typeof value === "number")
|
|
91
|
+
values.push(value);
|
|
92
|
+
index++;
|
|
183
93
|
}
|
|
184
94
|
}
|
|
185
|
-
|
|
186
|
-
|
|
95
|
+
const stringLiterals = createTemplateStringsArray(literalsArray);
|
|
96
|
+
return constructMiniHtmlString(stringLiterals, values);
|
|
97
|
+
}
|
|
98
|
+
function combineMiniHtmlStrings(htmlstrings) {
|
|
99
|
+
const stringLiterals = combineTemplateStringsArrays(htmlstrings.map((hs) => hs.stringLiterals));
|
|
100
|
+
const values = htmlstrings.flatMap((hs) => hs.values);
|
|
101
|
+
return constructMiniHtmlString(stringLiterals, values);
|
|
187
102
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
103
|
+
function combineTemplateStringsArrays(tsas) {
|
|
104
|
+
const stringlits = [];
|
|
105
|
+
for (const litarray of tsas) {
|
|
106
|
+
const prior = stringlits.at(-1);
|
|
107
|
+
const first = litarray[0];
|
|
108
|
+
if (prior && first) {
|
|
109
|
+
stringlits[stringlits.length - 1] += first;
|
|
110
|
+
stringlits.push(...litarray.slice(1));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
stringlits.push(...litarray);
|
|
196
114
|
}
|
|
197
|
-
socket = new WebSocket("ws://localhost:3001/reload");
|
|
198
|
-
|
|
199
|
-
socket.addEventListener("message", (event) => {
|
|
200
|
-
window.location.reload();
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
socket.addEventListener("close", (event) => {
|
|
204
|
-
// Reestablish the connection after 1 second
|
|
205
|
-
socket = null;
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
socket.addEventListener("error", (event) => {
|
|
209
|
-
socket = null;
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
connectWebSocket(); // connect to reloader, if it does not work:
|
|
213
|
-
setInterval(connectWebSocket, 1000); // retry every 1 second
|
|
214
|
-
}
|
|
215
|
-
reloader();
|
|
216
|
-
</script>
|
|
217
|
-
`;
|
|
218
|
-
async function makeEntrypoint() {
|
|
219
|
-
let module;
|
|
220
|
-
const backendImportPath = projectRoot() + "/dist/backend.js";
|
|
221
|
-
try {
|
|
222
|
-
// @ts-ignore
|
|
223
|
-
module = await import(backendImportPath);
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
await build();
|
|
227
|
-
// @ts-ignore
|
|
228
|
-
module = await import(backendImportPath);
|
|
229
115
|
}
|
|
230
|
-
return
|
|
116
|
+
return createTemplateStringsArray(stringlits);
|
|
231
117
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
118
|
+
function createTemplateStringsArray(strings) {
|
|
119
|
+
const stringsArray = [...strings];
|
|
120
|
+
const frozenRaw = Object.freeze([...strings]);
|
|
121
|
+
Object.defineProperty(stringsArray, "raw", {
|
|
122
|
+
value: frozenRaw,
|
|
123
|
+
writable: false,
|
|
124
|
+
enumerable: false,
|
|
125
|
+
configurable: false,
|
|
126
|
+
});
|
|
127
|
+
return Object.freeze(stringsArray);
|
|
128
|
+
}
|
|
129
|
+
export function resolveMiniValue(value, parentMini, slotId) {
|
|
130
|
+
// make new mini with slotid as cursor
|
|
131
|
+
const mini = makeNewMini({ ...parentMini.cacheAndCursor, cursor: slotId });
|
|
132
|
+
if (typeof value === "function") {
|
|
133
|
+
const component = value(mini);
|
|
134
|
+
// if this happened we need to save the state to the cache
|
|
135
|
+
return component.resolve(mini);
|
|
136
|
+
}
|
|
137
|
+
if (value && typeof value === "object" && "resolve" in value)
|
|
138
|
+
return value.resolve(mini);
|
|
139
|
+
return value;
|
|
241
140
|
}
|
|
242
|
-
export { has, html, url, head, build, makeEntrypoint, isError, BasedHtml, HtmlString, Mini, standardDevReloader, commonHead, cssReset, };
|
package/package.json
CHANGED
package/dist/html.d.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import type { HandlerReturnType, HtmlHandler, LazyHandlerReturnType, Mini } from "./url";
|
|
2
|
-
export type HtmlStringValues<T = unknown> = HtmlString | HtmlString[] | BasedHtml | BasedHtml[] | (BasedHtml | HtmlString)[] | string | number | HtmlHandler<T> | JsonString | LazyHandlerReturnType | undefined;
|
|
3
|
-
export type JsonStringValues<T = unknown> = HtmlStringValues<T> | {
|
|
4
|
-
[key: string]: any;
|
|
5
|
-
};
|
|
6
|
-
export declare class HtmlString extends Array {
|
|
7
|
-
/**
|
|
8
|
-
* a HtmlString is by default resolved.
|
|
9
|
-
* if we we pass a function as a value to the html`` template string, it will be unresolved.
|
|
10
|
-
* it can also become unresolved if an unresolved HtmlString is passed into it as a value
|
|
11
|
-
*/
|
|
12
|
-
resolved: boolean;
|
|
13
|
-
resolve<T>(mini: Mini<T>): Promise<this>;
|
|
14
|
-
flat(depth?: number): this;
|
|
15
|
-
}
|
|
16
|
-
export declare function html<X = unknown>(strings: TemplateStringsArray, ...values: HtmlStringValues<X>[]): HtmlString;
|
|
17
|
-
export declare class JsonString extends HtmlString {
|
|
18
|
-
}
|
|
19
|
-
export declare class DangerJsonInHtml extends HtmlString {
|
|
20
|
-
}
|
|
21
|
-
export declare const json: <X = unknown>(strings: TemplateStringsArray, ...values: JsonStringValues<X>[]) => JsonString;
|
|
22
|
-
export declare const dangerjson: <X = unknown>(strings: TemplateStringsArray, ...values: JsonStringValues<X>[]) => DangerJsonInHtml;
|
|
23
|
-
export declare const commonHead: HtmlString;
|
|
24
|
-
export declare const cssReset: HtmlString;
|
|
25
|
-
/**
|
|
26
|
-
* Set the default head for all pages. Can still be overwritten on a per page basis
|
|
27
|
-
* @param defaultHead - HtmlString
|
|
28
|
-
*
|
|
29
|
-
* @example Here is what a default head might look like:
|
|
30
|
-
* ```ts
|
|
31
|
-
*head((mini)=>mini.html` <title>hello hello</title> `);
|
|
32
|
-
* url.set([
|
|
33
|
-
* ["/", (mini) => mini.html`<h1>Hello world</h1>`],
|
|
34
|
-
* [
|
|
35
|
-
* "/bye",
|
|
36
|
-
* (mini) =>
|
|
37
|
-
* mini.html`<h1>Goodbye world</h1>${mini.head(
|
|
38
|
-
* mini.html` <title>bye bye</title>`
|
|
39
|
-
* )}`,
|
|
40
|
-
* ],
|
|
41
|
-
* ]);
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export declare function head(defaultHead: HtmlHandler): void;
|
|
45
|
-
export declare function htmlResponder(mini: Mini, maybeUnresolved: HandlerReturnType, head?: HtmlHandler, options?: ResponseInit): Promise<Response>;
|
|
46
|
-
/**
|
|
47
|
-
* Generic html error type guard
|
|
48
|
-
* @param submissionResult output of some function
|
|
49
|
-
* @returns boolean - true if the given object has a property called "error" and its value is an instance of HtmlString
|
|
50
|
-
*/
|
|
51
|
-
export declare function isError(submissionResult: any | {
|
|
52
|
-
error: HtmlString;
|
|
53
|
-
}): submissionResult is {
|
|
54
|
-
error: HtmlString;
|
|
55
|
-
};
|
|
56
|
-
declare global {
|
|
57
|
-
var Reloader: BasedHtml | HtmlString | undefined;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* The difference between this and HtmlString is that it is fully resolved and only accepts primitive types.
|
|
61
|
-
* In plain english this means:
|
|
62
|
-
* It does not accept functions (that will be resolved at request time with (mini)=>mini.html) like mini.html does.
|
|
63
|
-
*/
|
|
64
|
-
export declare class BasedHtml extends String {
|
|
65
|
-
}
|
|
66
|
-
export type BasedHtmlValues = number | string | undefined | null | boolean | BasedHtml | BasedHtml[];
|
|
67
|
-
/**
|
|
68
|
-
* The difference between this and HtmlString is that it is fully resolved and only accepts primitive types.
|
|
69
|
-
* @param strings - html literals
|
|
70
|
-
* @param values - values will get escaped to prevent xss
|
|
71
|
-
* @returns
|
|
72
|
-
*/
|
|
73
|
-
export declare const basedHtml: (strings: TemplateStringsArray, ...values: BasedHtmlValues[]) => BasedHtml;
|