@seed-ship/mcp-ui-solid 6.22.0 → 6.24.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/CHANGELOG.md +219 -0
- package/README.md +209 -2
- package/dist/components/ChartJSRenderer.cjs +192 -66
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +192 -66
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/DegradedFallback.cjs +34 -2
- package/dist/components/DegradedFallback.cjs.map +1 -1
- package/dist/components/DegradedFallback.d.ts +7 -0
- package/dist/components/DegradedFallback.d.ts.map +1 -1
- package/dist/components/DegradedFallback.js +34 -2
- package/dist/components/DegradedFallback.js.map +1 -1
- package/dist/components/MissingValue.cjs +43 -0
- package/dist/components/MissingValue.cjs.map +1 -0
- package/dist/components/MissingValue.d.ts +27 -0
- package/dist/components/MissingValue.d.ts.map +1 -0
- package/dist/components/MissingValue.js +43 -0
- package/dist/components/MissingValue.js.map +1 -0
- package/dist/components/UIResourceRenderer.cjs +250 -202
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts +2 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +250 -202
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/chart-data-table.cjs +30 -5
- package/dist/components/chart-data-table.cjs.map +1 -1
- package/dist/components/chart-data-table.d.ts +18 -1
- package/dist/components/chart-data-table.d.ts.map +1 -1
- package/dist/components/chart-data-table.js +30 -5
- package/dist/components/chart-data-table.js.map +1 -1
- package/dist/components/chart-missing-plugin.cjs +194 -0
- package/dist/components/chart-missing-plugin.cjs.map +1 -0
- package/dist/components/chart-missing-plugin.d.ts +127 -0
- package/dist/components/chart-missing-plugin.d.ts.map +1 -0
- package/dist/components/chart-missing-plugin.js +194 -0
- package/dist/components/chart-missing-plugin.js.map +1 -0
- package/dist/context/MCPUIConfigContext.cjs.map +1 -1
- package/dist/context/MCPUIConfigContext.d.ts +57 -28
- package/dist/context/MCPUIConfigContext.d.ts.map +1 -1
- package/dist/context/MCPUIConfigContext.js.map +1 -1
- package/dist/context/MCPUIMathContext.cjs +19 -0
- package/dist/context/MCPUIMathContext.cjs.map +1 -0
- package/dist/context/MCPUIMathContext.d.ts +18 -0
- package/dist/context/MCPUIMathContext.d.ts.map +1 -0
- package/dist/context/MCPUIMathContext.js +19 -0
- package/dist/context/MCPUIMathContext.js.map +1 -0
- package/dist/context/MCPUIStringsContext.cjs +12 -1
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +62 -0
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +12 -1
- package/dist/context/MCPUIStringsContext.js.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/katex.cjs +23 -0
- package/dist/plugins/katex.cjs.map +1 -0
- package/dist/plugins/katex.d.cts +7 -0
- package/dist/plugins/katex.d.ts +7 -0
- package/dist/plugins/katex.d.ts.map +1 -0
- package/dist/plugins/katex.js +23 -0
- package/dist/plugins/katex.js.map +1 -0
- package/dist/services/component-registry.cjs +9 -2
- package/dist/services/component-registry.cjs.map +1 -1
- package/dist/services/component-registry.d.ts.map +1 -1
- package/dist/services/component-registry.js +9 -2
- package/dist/services/component-registry.js.map +1 -1
- package/dist/services/validation.cjs +31 -8
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +31 -8
- package/dist/services/validation.js.map +1 -1
- package/dist/types/index.d.ts +14 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/degraded-projections.cjs +19 -3
- package/dist/utils/degraded-projections.cjs.map +1 -1
- package/dist/utils/degraded-projections.d.ts +22 -2
- package/dist/utils/degraded-projections.d.ts.map +1 -1
- package/dist/utils/degraded-projections.js +19 -3
- package/dist/utils/degraded-projections.js.map +1 -1
- package/dist/utils/iframe-coep.cjs.map +1 -1
- package/dist/utils/iframe-coep.d.ts +7 -6
- package/dist/utils/iframe-coep.d.ts.map +1 -1
- package/dist/utils/iframe-coep.js.map +1 -1
- package/dist/utils/math-markdown.cjs +240 -0
- package/dist/utils/math-markdown.cjs.map +1 -0
- package/dist/utils/math-markdown.d.ts +16 -0
- package/dist/utils/math-markdown.d.ts.map +1 -0
- package/dist/utils/math-markdown.js +240 -0
- package/dist/utils/math-markdown.js.map +1 -0
- package/dist/utils/missing-value.cjs +60 -0
- package/dist/utils/missing-value.cjs.map +1 -0
- package/dist/utils/missing-value.d.ts +79 -0
- package/dist/utils/missing-value.d.ts.map +1 -0
- package/dist/utils/missing-value.js +60 -0
- package/dist/utils/missing-value.js.map +1 -0
- package/package.json +23 -4
- package/src/components/ChartJSRenderer.tsx +159 -6
- package/src/components/DegradedFallback.tsx +24 -2
- package/src/components/MissingValue.tsx +61 -0
- package/src/components/UIResourceRenderer.tsx +64 -10
- package/src/components/chart-data-table.ts +50 -6
- package/src/components/chart-missing-plugin.ts +334 -0
- package/src/context/MCPUIConfigContext.tsx +57 -28
- package/src/context/MCPUIMathContext.tsx +32 -0
- package/src/context/MCPUIStringsContext.tsx +76 -0
- package/src/index.ts +4 -0
- package/src/plugins/katex.ts +25 -0
- package/src/services/component-registry.ts +10 -2
- package/src/services/validation.ts +44 -9
- package/src/types/index.ts +13 -1
- package/src/utils/degraded-projections.ts +44 -4
- package/src/utils/iframe-coep.ts +7 -6
- package/src/utils/math-markdown.ts +222 -0
- package/src/utils/missing-value.ts +127 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { Marked, Renderer } from "marked";
|
|
2
|
+
import { escapeHtml } from "./escape-html.js";
|
|
3
|
+
import { canSanitizeHtml, sanitizeHtml } from "./sanitize-html.js";
|
|
4
|
+
const MATH_MARKDOWN_LIMITS = {
|
|
5
|
+
sourceLength: 1e5,
|
|
6
|
+
expressionLength: 4096,
|
|
7
|
+
expressionCount: 128
|
|
8
|
+
};
|
|
9
|
+
const MATH_TAGS = [
|
|
10
|
+
"math",
|
|
11
|
+
"semantics",
|
|
12
|
+
"mrow",
|
|
13
|
+
"mi",
|
|
14
|
+
"mo",
|
|
15
|
+
"mn",
|
|
16
|
+
"mtext",
|
|
17
|
+
"mspace",
|
|
18
|
+
"ms",
|
|
19
|
+
"msup",
|
|
20
|
+
"msub",
|
|
21
|
+
"msubsup",
|
|
22
|
+
"mfrac",
|
|
23
|
+
"msqrt",
|
|
24
|
+
"mroot",
|
|
25
|
+
"mtable",
|
|
26
|
+
"mtr",
|
|
27
|
+
"mtd",
|
|
28
|
+
"mover",
|
|
29
|
+
"munder",
|
|
30
|
+
"munderover",
|
|
31
|
+
"mpadded",
|
|
32
|
+
"mphantom",
|
|
33
|
+
"mstyle",
|
|
34
|
+
"menclose"
|
|
35
|
+
];
|
|
36
|
+
const MATH_ATTRS = [
|
|
37
|
+
"xmlns",
|
|
38
|
+
"display",
|
|
39
|
+
"class",
|
|
40
|
+
"mathvariant",
|
|
41
|
+
"stretchy",
|
|
42
|
+
"fence",
|
|
43
|
+
"separator",
|
|
44
|
+
"lspace",
|
|
45
|
+
"rspace",
|
|
46
|
+
"accent",
|
|
47
|
+
"accentunder",
|
|
48
|
+
"columnalign",
|
|
49
|
+
"rowalign",
|
|
50
|
+
"columnspacing",
|
|
51
|
+
"rowspacing",
|
|
52
|
+
"columnlines",
|
|
53
|
+
"rowlines",
|
|
54
|
+
"frame",
|
|
55
|
+
"notation",
|
|
56
|
+
"width",
|
|
57
|
+
"height",
|
|
58
|
+
"depth",
|
|
59
|
+
"voffset",
|
|
60
|
+
"scriptlevel",
|
|
61
|
+
"displaystyle"
|
|
62
|
+
];
|
|
63
|
+
const STRICT_MATHML_CONFIG = {
|
|
64
|
+
ALLOWED_TAGS: [...MATH_TAGS, "span"],
|
|
65
|
+
ALLOWED_ATTR: [...MATH_ATTRS],
|
|
66
|
+
FORBID_TAGS: ["annotation", "annotation-xml", "style", "a"],
|
|
67
|
+
// DOMPurify normally keeps the text of forbidden tags. TeX annotations can
|
|
68
|
+
// be large and duplicate the accessible MathML, so remove their subtree.
|
|
69
|
+
ADD_FORBID_CONTENTS: ["annotation", "annotation-xml"],
|
|
70
|
+
FORBID_ATTR: ["style"]
|
|
71
|
+
};
|
|
72
|
+
const CELL_MARKDOWN_TAGS = [
|
|
73
|
+
"a",
|
|
74
|
+
"strong",
|
|
75
|
+
"em",
|
|
76
|
+
"b",
|
|
77
|
+
"i",
|
|
78
|
+
"code",
|
|
79
|
+
"span",
|
|
80
|
+
"br",
|
|
81
|
+
"button",
|
|
82
|
+
"svg",
|
|
83
|
+
"path",
|
|
84
|
+
"p",
|
|
85
|
+
"ul",
|
|
86
|
+
"ol",
|
|
87
|
+
"li",
|
|
88
|
+
"pre",
|
|
89
|
+
"blockquote",
|
|
90
|
+
"h1",
|
|
91
|
+
"h2",
|
|
92
|
+
"h3",
|
|
93
|
+
"h4",
|
|
94
|
+
"h5",
|
|
95
|
+
"h6",
|
|
96
|
+
...MATH_TAGS
|
|
97
|
+
];
|
|
98
|
+
const FINAL_PROFILES = {
|
|
99
|
+
prose: {
|
|
100
|
+
ADD_TAGS: [...MATH_TAGS],
|
|
101
|
+
ADD_ATTR: [...MATH_ATTRS, "target", "rel"],
|
|
102
|
+
FORBID_TAGS: ["annotation", "annotation-xml", "style", "form", "textarea", "select", "button", "iframe", "object", "embed"],
|
|
103
|
+
ADD_FORBID_CONTENTS: ["annotation", "annotation-xml"],
|
|
104
|
+
FORBID_ATTR: ["style"]
|
|
105
|
+
},
|
|
106
|
+
cellMarkdown: {
|
|
107
|
+
ALLOWED_TAGS: CELL_MARKDOWN_TAGS,
|
|
108
|
+
ALLOWED_ATTR: [
|
|
109
|
+
"href",
|
|
110
|
+
"target",
|
|
111
|
+
"rel",
|
|
112
|
+
"class",
|
|
113
|
+
"data-citation-page",
|
|
114
|
+
"data-citation-source",
|
|
115
|
+
"data-citation-doc",
|
|
116
|
+
"data-citation-verified",
|
|
117
|
+
"title",
|
|
118
|
+
"fill",
|
|
119
|
+
"stroke",
|
|
120
|
+
"viewBox",
|
|
121
|
+
"stroke-linecap",
|
|
122
|
+
"stroke-linejoin",
|
|
123
|
+
"stroke-width",
|
|
124
|
+
"d",
|
|
125
|
+
...MATH_ATTRS
|
|
126
|
+
],
|
|
127
|
+
FORBID_TAGS: ["annotation", "annotation-xml", "style"],
|
|
128
|
+
ADD_FORBID_CONTENTS: ["annotation", "annotation-xml"],
|
|
129
|
+
FORBID_ATTR: ["style"]
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
function isCurrencyLike(raw, tex, following) {
|
|
133
|
+
var _a, _b, _c;
|
|
134
|
+
if (/^\$\s|\s\$$/.test(raw)) return true;
|
|
135
|
+
if (/^\d+(?:[.,]\d+)?-\s*$/.test(tex)) return true;
|
|
136
|
+
if (/^\d/.test(tex) && /^\d/.test(following)) return true;
|
|
137
|
+
const amount = (_a = /^\d+(?:[.,]\d{1,2})?(?=$|[\s,;:!?()[\]+*/-])/.exec(tex)) == null ? void 0 : _a[0];
|
|
138
|
+
if (!amount) return false;
|
|
139
|
+
const trailing = tex.slice(amount.length);
|
|
140
|
+
if (!trailing) return false;
|
|
141
|
+
const hasUnmatchedOpeningParen = (((_b = trailing.match(/\(/g)) == null ? void 0 : _b.length) ?? 0) > (((_c = trailing.match(/\)/g)) == null ? void 0 : _c.length) ?? 0);
|
|
142
|
+
const containsTexCommand = /\\[A-Za-z]+/.test(trailing);
|
|
143
|
+
if (hasUnmatchedOpeningParen && !containsTexCommand) return true;
|
|
144
|
+
const closerLooksLikeLaterOpener = /^(?![\s,.;:!?)}\]])(?:\\[^\n]|[^\\\n$])+\$(?!\$)/.test(following);
|
|
145
|
+
return closerLooksLikeLaterOpener;
|
|
146
|
+
}
|
|
147
|
+
const CELL_LINK_ATTRIBUTES = 'target="_blank" rel="noopener noreferrer" class="text-blue-600 dark:text-blue-400 hover:underline"';
|
|
148
|
+
function cellLinkExtension() {
|
|
149
|
+
return {
|
|
150
|
+
renderer: {
|
|
151
|
+
link(token) {
|
|
152
|
+
const anchor = Renderer.prototype.link.call(this, token);
|
|
153
|
+
return anchor.replace("<a ", `<a ${CELL_LINK_ATTRIBUTES} `);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function mathExtension(renderer) {
|
|
159
|
+
let count = 0;
|
|
160
|
+
const token = (raw, tex, displayMode) => ({
|
|
161
|
+
type: displayMode ? "mcpDisplayMath" : "mcpInlineMath",
|
|
162
|
+
raw,
|
|
163
|
+
tex,
|
|
164
|
+
displayMode,
|
|
165
|
+
render: ++count <= MATH_MARKDOWN_LIMITS.expressionCount && tex.length <= MATH_MARKDOWN_LIMITS.expressionLength
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
extensions: [
|
|
169
|
+
{
|
|
170
|
+
name: "mcpDisplayMath",
|
|
171
|
+
level: "block",
|
|
172
|
+
start(src) {
|
|
173
|
+
const index = src.indexOf("$$");
|
|
174
|
+
return index < 0 ? void 0 : index;
|
|
175
|
+
},
|
|
176
|
+
tokenizer(src) {
|
|
177
|
+
const match = /^\$\$\s*\n?([\s\S]+?)\n?\s*\$\$(?:\n|$)/.exec(src);
|
|
178
|
+
if (!match) return void 0;
|
|
179
|
+
return token(match[0], match[1], true);
|
|
180
|
+
},
|
|
181
|
+
renderer(tokenValue) {
|
|
182
|
+
return renderToken(tokenValue, renderer);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: "mcpInlineMath",
|
|
187
|
+
level: "inline",
|
|
188
|
+
start(src) {
|
|
189
|
+
const index = src.indexOf("$");
|
|
190
|
+
return index < 0 ? void 0 : index;
|
|
191
|
+
},
|
|
192
|
+
tokenizer(src) {
|
|
193
|
+
const match = /^\$(?!\$)((?:\\[^\n]|[^\\\n$])+?)\$(?!\$)/.exec(src);
|
|
194
|
+
if (!match || isCurrencyLike(match[0], match[1], src.slice(match[0].length))) return void 0;
|
|
195
|
+
return token(match[0], match[1], false);
|
|
196
|
+
},
|
|
197
|
+
renderer(tokenValue) {
|
|
198
|
+
return renderToken(tokenValue, renderer);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function renderToken(token, renderer) {
|
|
205
|
+
if (!token.render) return escapeHtml(token.raw);
|
|
206
|
+
try {
|
|
207
|
+
const rendered = renderer(token.tex, { displayMode: token.displayMode });
|
|
208
|
+
if (!rendered) return escapeHtml(token.raw);
|
|
209
|
+
return sanitizeHtml(rendered, STRICT_MATHML_CONFIG);
|
|
210
|
+
} catch {
|
|
211
|
+
return escapeHtml(token.raw);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function parseMathMarkdown(source, renderer, profile, transformText) {
|
|
215
|
+
const input = source === null || source === void 0 ? "" : String(source);
|
|
216
|
+
if (!canSanitizeHtml()) return escapeHtml(input);
|
|
217
|
+
if (input.length > MATH_MARKDOWN_LIMITS.sourceLength) return escapeHtml(input);
|
|
218
|
+
const textRenderer = transformText ? {
|
|
219
|
+
renderer: {
|
|
220
|
+
text(token) {
|
|
221
|
+
if ("tokens" in token && token.tokens) {
|
|
222
|
+
return this.parser.parseInline(token.tokens);
|
|
223
|
+
}
|
|
224
|
+
const safeText = Renderer.prototype.text.call(this, token);
|
|
225
|
+
return transformText(safeText);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
} : void 0;
|
|
229
|
+
const extensions = [mathExtension(renderer)];
|
|
230
|
+
if (profile === "cellMarkdown") extensions.push(cellLinkExtension());
|
|
231
|
+
if (textRenderer) extensions.push(textRenderer);
|
|
232
|
+
const parser = new Marked({ gfm: true }, ...extensions);
|
|
233
|
+
const parsed = parser.parse(input, { async: false });
|
|
234
|
+
return sanitizeHtml(parsed, FINAL_PROFILES[profile]);
|
|
235
|
+
}
|
|
236
|
+
export {
|
|
237
|
+
MATH_MARKDOWN_LIMITS,
|
|
238
|
+
parseMathMarkdown
|
|
239
|
+
};
|
|
240
|
+
//# sourceMappingURL=math-markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"math-markdown.js","sources":["../../src/utils/math-markdown.ts"],"sourcesContent":["import type { Config } from 'dompurify'\nimport { Marked, Renderer, type MarkedExtension, type Tokens } from 'marked'\nimport type { MathRenderer } from '../context/MCPUIMathContext'\nimport { escapeHtml } from './escape-html'\nimport { canSanitizeHtml, sanitizeHtml } from './sanitize-html'\n\nexport type MathMarkdownProfile = 'prose' | 'cellMarkdown'\nexport type MarkdownTextTransform = (escapedText: string) => string\n\nexport const MATH_MARKDOWN_LIMITS = {\n sourceLength: 100_000,\n expressionLength: 4_096,\n expressionCount: 128,\n} as const\n\nconst MATH_TAGS = [\n 'math', 'semantics', 'mrow', 'mi', 'mo', 'mn', 'mtext', 'mspace', 'ms',\n 'msup', 'msub', 'msubsup', 'mfrac', 'msqrt', 'mroot', 'mtable', 'mtr',\n 'mtd', 'mover', 'munder', 'munderover', 'mpadded', 'mphantom', 'mstyle', 'menclose',\n] as const\n\nconst MATH_ATTRS = [\n 'xmlns', 'display', 'class', 'mathvariant', 'stretchy', 'fence', 'separator',\n 'lspace', 'rspace', 'accent', 'accentunder', 'columnalign', 'rowalign',\n 'columnspacing', 'rowspacing', 'columnlines', 'rowlines', 'frame', 'notation',\n 'width', 'height', 'depth', 'voffset', 'scriptlevel', 'displaystyle',\n] as const\n\nconst STRICT_MATHML_CONFIG = {\n ALLOWED_TAGS: [...MATH_TAGS, 'span'],\n ALLOWED_ATTR: [...MATH_ATTRS],\n FORBID_TAGS: ['annotation', 'annotation-xml', 'style', 'a'],\n // DOMPurify normally keeps the text of forbidden tags. TeX annotations can\n // be large and duplicate the accessible MathML, so remove their subtree.\n ADD_FORBID_CONTENTS: ['annotation', 'annotation-xml'],\n FORBID_ATTR: ['style'],\n} as Config\n\nconst CELL_MARKDOWN_TAGS = [\n 'a', 'strong', 'em', 'b', 'i', 'code', 'span', 'br', 'button', 'svg', 'path',\n 'p', 'ul', 'ol', 'li', 'pre', 'blockquote', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n ...MATH_TAGS,\n]\n\nconst FINAL_PROFILES: Record<MathMarkdownProfile, Config> = {\n prose: {\n ADD_TAGS: [...MATH_TAGS],\n ADD_ATTR: [...MATH_ATTRS, 'target', 'rel'],\n FORBID_TAGS: ['annotation', 'annotation-xml', 'style', 'form', 'textarea', 'select', 'button', 'iframe', 'object', 'embed'],\n ADD_FORBID_CONTENTS: ['annotation', 'annotation-xml'],\n FORBID_ATTR: ['style'],\n } as Config,\n cellMarkdown: {\n ALLOWED_TAGS: CELL_MARKDOWN_TAGS,\n ALLOWED_ATTR: [\n 'href', 'target', 'rel', 'class', 'data-citation-page', 'data-citation-source',\n 'data-citation-doc', 'data-citation-verified', 'title', 'fill', 'stroke',\n 'viewBox', 'stroke-linecap', 'stroke-linejoin', 'stroke-width', 'd',\n ...MATH_ATTRS,\n ],\n FORBID_TAGS: ['annotation', 'annotation-xml', 'style'],\n ADD_FORBID_CONTENTS: ['annotation', 'annotation-xml'],\n FORBID_ATTR: ['style'],\n } as Config,\n}\n\ninterface MathToken extends Tokens.Generic {\n type: 'mcpDisplayMath' | 'mcpInlineMath'\n raw: string\n tex: string\n displayMode: boolean\n render: boolean\n}\n\nfunction isCurrencyLike(raw: string, tex: string, following: string): boolean {\n if (/^\\$\\s|\\s\\$$/.test(raw)) return true\n if (/^\\d+(?:[.,]\\d+)?-\\s*$/.test(tex)) return true\n if (/^\\d/.test(tex) && /^\\d/.test(following)) return true\n\n // A currency opener can otherwise pair with the opening delimiter of a\n // later expression (\"$5 then ($x$)\"). Reinterpret that first candidate\n // only when it starts with a bounded numeric amount and its apparent closer\n // is immediately followed by a complete later inline body. This deliberately\n // leaves inherently ambiguous standalone forms ($5$, $2 + 3$, $2\\pi$) as\n // math and does not depend on the prose between the two delimiters.\n const amount = /^\\d+(?:[.,]\\d{1,2})?(?=$|[\\s,;:!?()[\\]+*/-])/.exec(tex)?.[0]\n if (!amount) return false\n\n // A standalone numeric token is valid math even when followed by prose or\n // another expression (\"$5$, then $x$\"). Reassignment requires content\n // beyond the amount itself.\n const trailing = tex.slice(amount.length)\n if (!trailing) return false\n\n // During streaming, the later formula may not have closed yet. An unmatched\n // opening parenthesis before its dollar is sufficient structural evidence\n // that the numeric dollar was currency; otherwise a permissive renderer can\n // briefly flash \"5 then (\" as math.\n const hasUnmatchedOpeningParen = (trailing.match(/\\(/g)?.length ?? 0) > (trailing.match(/\\)/g)?.length ?? 0)\n const containsTexCommand = /\\\\[A-Za-z]+/.test(trailing)\n if (hasUnmatchedOpeningParen && !containsTexCommand) return true\n\n const closerLooksLikeLaterOpener = /^(?![\\s,.;:!?)}\\]])(?:\\\\[^\\n]|[^\\\\\\n$])+\\$(?!\\$)/.test(following)\n return closerLooksLikeLaterOpener\n}\n\nconst CELL_LINK_ATTRIBUTES = 'target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-blue-600 dark:text-blue-400 hover:underline\"'\n\nfunction cellLinkExtension(): MarkedExtension {\n return {\n renderer: {\n link(this: Renderer, token: Tokens.Link): string {\n // Marked owns escaping of the destination, title and nested label\n // tokens. Only inject fixed attributes into its already-safe anchor.\n const anchor = Renderer.prototype.link.call(this, token) as string\n return anchor.replace('<a ', `<a ${CELL_LINK_ATTRIBUTES} `)\n },\n },\n }\n}\n\nfunction mathExtension(renderer: MathRenderer): MarkedExtension {\n let count = 0\n const token = (raw: string, tex: string, displayMode: boolean): MathToken => ({\n type: displayMode ? 'mcpDisplayMath' : 'mcpInlineMath',\n raw,\n tex,\n displayMode,\n render: ++count <= MATH_MARKDOWN_LIMITS.expressionCount && tex.length <= MATH_MARKDOWN_LIMITS.expressionLength,\n })\n\n return {\n extensions: [\n {\n name: 'mcpDisplayMath',\n level: 'block',\n start(src) {\n const index = src.indexOf('$$')\n return index < 0 ? undefined : index\n },\n tokenizer(src) {\n const match = /^\\$\\$\\s*\\n?([\\s\\S]+?)\\n?\\s*\\$\\$(?:\\n|$)/.exec(src)\n if (!match) return undefined\n return token(match[0], match[1], true)\n },\n renderer(tokenValue) {\n return renderToken(tokenValue as MathToken, renderer)\n },\n },\n {\n name: 'mcpInlineMath',\n level: 'inline',\n start(src) {\n const index = src.indexOf('$')\n return index < 0 ? undefined : index\n },\n tokenizer(src) {\n const match = /^\\$(?!\\$)((?:\\\\[^\\n]|[^\\\\\\n$])+?)\\$(?!\\$)/.exec(src)\n if (!match || isCurrencyLike(match[0], match[1], src.slice(match[0].length))) return undefined\n return token(match[0], match[1], false)\n },\n renderer(tokenValue) {\n return renderToken(tokenValue as MathToken, renderer)\n },\n },\n ],\n }\n}\n\nfunction renderToken(token: MathToken, renderer: MathRenderer): string {\n if (!token.render) return escapeHtml(token.raw)\n try {\n const rendered = renderer(token.tex, { displayMode: token.displayMode })\n if (!rendered) return escapeHtml(token.raw)\n return sanitizeHtml(rendered, STRICT_MATHML_CONFIG)\n } catch {\n return escapeHtml(token.raw)\n }\n}\n\n/**\n * Parse Markdown with isolated, bounded math support and sanitize the complete\n * result for its final sink. The optional transform sees escaped ordinary text\n * tokens only. Math, code, raw HTML and link destinations never pass through\n * it, so citation syntax cannot corrupt TeX optional arguments or attributes.\n */\nexport function parseMathMarkdown(\n source: string,\n renderer: MathRenderer,\n profile: MathMarkdownProfile,\n transformText?: MarkdownTextTransform,\n): string {\n const input = source === null || source === undefined ? '' : String(source)\n if (!canSanitizeHtml()) return escapeHtml(input)\n if (input.length > MATH_MARKDOWN_LIMITS.sourceLength) return escapeHtml(input)\n\n const textRenderer = transformText\n ? {\n renderer: {\n text(this: Renderer, token: Tokens.Text | Tokens.Escape): string {\n // Block text tokens (notably list-item text) can own already\n // tokenized inline children. Recurse first so math and code keep\n // their own renderers; leaf text callbacks run as parsing descends.\n if ('tokens' in token && token.tokens) {\n return this.parser.parseInline(token.tokens)\n }\n // Delegate entity handling and nested token rendering to Marked's\n // own renderer. `escapeHtml` is deliberately not equivalent: it\n // turns source `&` into visible `&` by double-escaping it.\n const safeText = Renderer.prototype.text.call(this, token)\n return transformText(safeText as string)\n },\n },\n }\n : undefined\n const extensions = [mathExtension(renderer)]\n if (profile === 'cellMarkdown') extensions.push(cellLinkExtension())\n if (textRenderer) extensions.push(textRenderer)\n const parser = new Marked({ gfm: true }, ...extensions)\n const parsed = parser.parse(input, { async: false }) as string\n return sanitizeHtml(parsed, FINAL_PROFILES[profile])\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const MISSING_VALUE_MARKER = "-";
|
|
4
|
+
const PART_TO_WHOLE_CHART_TYPES = /* @__PURE__ */ new Set([
|
|
5
|
+
"pie",
|
|
6
|
+
"doughnut",
|
|
7
|
+
"polarArea"
|
|
8
|
+
]);
|
|
9
|
+
function isMissingCellValue(value) {
|
|
10
|
+
if (value === null || value === void 0) return true;
|
|
11
|
+
if (typeof value === "object") return false;
|
|
12
|
+
const cleaned = stripUndefinedDebris(String(value)).trim();
|
|
13
|
+
return cleaned === "" || cleaned === MISSING_VALUE_MARKER || cleaned.toLowerCase() === "undefined";
|
|
14
|
+
}
|
|
15
|
+
function stripUndefinedDebris(value) {
|
|
16
|
+
return value.replace(/\s*[–-]\s*undefined\s*$/gi, "").replace(/^undefined\s*[–-]\s*/gi, "");
|
|
17
|
+
}
|
|
18
|
+
function isMissingChartValue(value) {
|
|
19
|
+
if (value === null || value === void 0) return true;
|
|
20
|
+
if (typeof value === "number") return !Number.isFinite(value);
|
|
21
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
22
|
+
const y = value.y;
|
|
23
|
+
return y === null || y === void 0 || typeof y === "number" && !Number.isFinite(y);
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
function summarizeChartMissing(params) {
|
|
28
|
+
var _a;
|
|
29
|
+
const datasets = Array.isArray((_a = params == null ? void 0 : params.data) == null ? void 0 : _a.datasets) ? params.data.datasets : [];
|
|
30
|
+
const fullyMissing = [];
|
|
31
|
+
const partiallyMissing = [];
|
|
32
|
+
let anyMissing = false;
|
|
33
|
+
let anyObserved = false;
|
|
34
|
+
for (const dataset of datasets) {
|
|
35
|
+
const data = Array.isArray(dataset == null ? void 0 : dataset.data) ? dataset.data : [];
|
|
36
|
+
let observed = 0;
|
|
37
|
+
let missing = 0;
|
|
38
|
+
for (const value of data) {
|
|
39
|
+
if (isMissingChartValue(value)) missing += 1;
|
|
40
|
+
else observed += 1;
|
|
41
|
+
}
|
|
42
|
+
fullyMissing.push(missing > 0 && observed === 0);
|
|
43
|
+
partiallyMissing.push(observed > 0 && missing > 0);
|
|
44
|
+
anyMissing || (anyMissing = missing > 0);
|
|
45
|
+
anyObserved || (anyObserved = observed > 0);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
hasMissing: anyMissing,
|
|
49
|
+
fullyMissing,
|
|
50
|
+
partiallyMissing,
|
|
51
|
+
allMissing: anyMissing && !anyObserved
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
exports.MISSING_VALUE_MARKER = MISSING_VALUE_MARKER;
|
|
55
|
+
exports.PART_TO_WHOLE_CHART_TYPES = PART_TO_WHOLE_CHART_TYPES;
|
|
56
|
+
exports.isMissingCellValue = isMissingCellValue;
|
|
57
|
+
exports.isMissingChartValue = isMissingChartValue;
|
|
58
|
+
exports.stripUndefinedDebris = stripUndefinedDebris;
|
|
59
|
+
exports.summarizeChartMissing = summarizeChartMissing;
|
|
60
|
+
//# sourceMappingURL=missing-value.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-value.cjs","sources":["../../src/utils/missing-value.ts"],"sourcesContent":["/**\n * Missing values — one definition shared by tables, chart data views,\n * degraded projections, chart validation and the chart renderer.\n *\n * @since v6.24.0\n *\n * A missing value is a value the payload says EXISTS but was not observed:\n * `null` in a chart dataset (or as a point's `y`), `null` / `undefined` in a\n * table cell. It is not a zero, and it is not the absence of a row or of a\n * label: every view keeps its slot and marks it.\n *\n * Runtime-free on purpose (no `solid-js`): the pure projections in\n * `chart-data-table.ts` and `degraded-projections.ts`, and `validation.ts`\n * (published as the `/validation` subpath), import it.\n */\n\n/** The glyph a table cell shows for a missing value — `renderCellValue`'s historical `-`. */\nexport const MISSING_VALUE_MARKER = '-'\n\n/**\n * Chart types that encode a value as a share of a whole (or, for polar area,\n * as a wedge whose emptiness reads as zero). Chart.js parses a `null` share\n * as `0`, so these types refuse missing values instead of drawing them.\n */\nexport const PART_TO_WHOLE_CHART_TYPES: ReadonlySet<string> = new Set([\n 'pie',\n 'doughnut',\n 'polarArea',\n])\n\n/**\n * Whether a raw TABLE cell value is displayed as {@link MISSING_VALUE_MARKER}.\n *\n * Mirrors the rules `renderCellValue` applies before any formatting — `null`,\n * `undefined`, and a string that is empty or the word `undefined` once the\n * backend's `\"X – undefined\"` debris is stripped — plus the literal marker\n * itself (whitespace around it aside, which a table cell does not render),\n * since it looks identical on screen and so must read identically.\n *\n * Objects are never missing here: `renderCellValue` renders them (link,\n * name, or escaped JSON).\n */\nexport function isMissingCellValue(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'object') return false\n const cleaned = stripUndefinedDebris(String(value)).trim()\n return cleaned === '' || cleaned === MISSING_VALUE_MARKER || cleaned.toLowerCase() === 'undefined'\n}\n\n/**\n * Removes the `\"Text – undefined\"` / `\"undefined – Text\"` debris some\n * backends concatenate. Shared with `renderCellValue` so both apply the very\n * same cleanup.\n */\nexport function stripUndefinedDebris(value: string): string {\n return value.replace(/\\s*[–-]\\s*undefined\\s*$/gi, '').replace(/^undefined\\s*[–-]\\s*/gi, '')\n}\n\n/**\n * Whether one CHART data entry is missing: `null` / `undefined`, a non-finite\n * number (Chart.js parses those to `null` too), or a point whose `y` is.\n */\nexport function isMissingChartValue(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'number') return !Number.isFinite(value)\n if (typeof value === 'object' && !Array.isArray(value)) {\n const y = (value as { y?: unknown }).y\n return y === null || y === undefined || (typeof y === 'number' && !Number.isFinite(y))\n }\n return false\n}\n\n/**\n * What a chart's missing values amount to.\n *\n * Only ENTRIES count: an explicit `null` (or non-finite number, or a point\n * whose `y` is one). A dataset with no entry at all (`data: []`) is not\n * \"missing\" — it is how 6.23.0 and earlier payloads said \"nothing yet\", e.g.\n * while streaming, and it keeps rendering exactly as it did then.\n */\nexport interface ChartMissingSummary {\n /** At least one entry of one dataset is missing. */\n hasMissing: boolean\n /** Per dataset, in order: it has entries and every one of them is missing. */\n fullyMissing: boolean[]\n /**\n * Per dataset, in order: at least one observed value AND at least one\n * missing entry — the series a reader actually sees broken.\n */\n partiallyMissing: boolean[]\n /** Something is missing and no dataset has a single observed value: nothing to plot. */\n allMissing: boolean\n}\n\ninterface ChartDataLike {\n data?: {\n datasets?: Array<{ data?: unknown[] } | null | undefined>\n }\n}\n\n/** Summarises the missing values of a chart payload. Never throws on a malformed payload. */\nexport function summarizeChartMissing(params: ChartDataLike | null | undefined): ChartMissingSummary {\n const datasets = Array.isArray(params?.data?.datasets) ? params.data.datasets : []\n const fullyMissing: boolean[] = []\n const partiallyMissing: boolean[] = []\n let anyMissing = false\n let anyObserved = false\n for (const dataset of datasets) {\n const data = Array.isArray(dataset?.data) ? dataset.data : []\n let observed = 0\n let missing = 0\n for (const value of data) {\n if (isMissingChartValue(value)) missing += 1\n else observed += 1\n }\n fullyMissing.push(missing > 0 && observed === 0)\n partiallyMissing.push(observed > 0 && missing > 0)\n anyMissing ||= missing > 0\n anyObserved ||= observed > 0\n }\n return {\n hasMissing: anyMissing,\n fullyMissing,\n partiallyMissing,\n allMissing: anyMissing && !anyObserved,\n }\n}\n"],"names":[],"mappings":";;AAiBO,MAAM,uBAAuB;AAO7B,MAAM,gDAAqD,IAAI;AAAA,EACpE;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAcM,SAAS,mBAAmB,OAAyB;AAC1D,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,qBAAqB,OAAO,KAAK,CAAC,EAAE,KAAA;AACpD,SAAO,YAAY,MAAM,YAAY,wBAAwB,QAAQ,kBAAkB;AACzF;AAOO,SAAS,qBAAqB,OAAuB;AAC1D,SAAO,MAAM,QAAQ,6BAA6B,EAAE,EAAE,QAAQ,0BAA0B,EAAE;AAC5F;AAMO,SAAS,oBAAoB,OAAyB;AAC3D,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,iBAAiB,CAAC,OAAO,SAAS,KAAK;AAC5D,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AACtD,UAAM,IAAK,MAA0B;AACrC,WAAO,MAAM,QAAQ,MAAM,UAAc,OAAO,MAAM,YAAY,CAAC,OAAO,SAAS,CAAC;AAAA,EACtF;AACA,SAAO;AACT;AA+BO,SAAS,sBAAsB,QAA+D;;AACnG,QAAM,WAAW,MAAM,SAAQ,sCAAQ,SAAR,mBAAc,QAAQ,IAAI,OAAO,KAAK,WAAW,CAAA;AAChF,QAAM,eAA0B,CAAA;AAChC,QAAM,mBAA8B,CAAA;AACpC,MAAI,aAAa;AACjB,MAAI,cAAc;AAClB,aAAW,WAAW,UAAU;AAC9B,UAAM,OAAO,MAAM,QAAQ,mCAAS,IAAI,IAAI,QAAQ,OAAO,CAAA;AAC3D,QAAI,WAAW;AACf,QAAI,UAAU;AACd,eAAW,SAAS,MAAM;AACxB,UAAI,oBAAoB,KAAK,EAAG,YAAW;AAAA,UACtC,aAAY;AAAA,IACnB;AACA,iBAAa,KAAK,UAAU,KAAK,aAAa,CAAC;AAC/C,qBAAiB,KAAK,WAAW,KAAK,UAAU,CAAC;AACjD,gCAAe,UAAU;AACzB,kCAAgB,WAAW;AAAA,EAC7B;AACA,SAAO;AAAA,IACL,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,YAAY,cAAc,CAAC;AAAA,EAAA;AAE/B;;;;;;;"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Missing values — one definition shared by tables, chart data views,
|
|
3
|
+
* degraded projections, chart validation and the chart renderer.
|
|
4
|
+
*
|
|
5
|
+
* @since v6.24.0
|
|
6
|
+
*
|
|
7
|
+
* A missing value is a value the payload says EXISTS but was not observed:
|
|
8
|
+
* `null` in a chart dataset (or as a point's `y`), `null` / `undefined` in a
|
|
9
|
+
* table cell. It is not a zero, and it is not the absence of a row or of a
|
|
10
|
+
* label: every view keeps its slot and marks it.
|
|
11
|
+
*
|
|
12
|
+
* Runtime-free on purpose (no `solid-js`): the pure projections in
|
|
13
|
+
* `chart-data-table.ts` and `degraded-projections.ts`, and `validation.ts`
|
|
14
|
+
* (published as the `/validation` subpath), import it.
|
|
15
|
+
*/
|
|
16
|
+
/** The glyph a table cell shows for a missing value — `renderCellValue`'s historical `-`. */
|
|
17
|
+
export declare const MISSING_VALUE_MARKER = "-";
|
|
18
|
+
/**
|
|
19
|
+
* Chart types that encode a value as a share of a whole (or, for polar area,
|
|
20
|
+
* as a wedge whose emptiness reads as zero). Chart.js parses a `null` share
|
|
21
|
+
* as `0`, so these types refuse missing values instead of drawing them.
|
|
22
|
+
*/
|
|
23
|
+
export declare const PART_TO_WHOLE_CHART_TYPES: ReadonlySet<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Whether a raw TABLE cell value is displayed as {@link MISSING_VALUE_MARKER}.
|
|
26
|
+
*
|
|
27
|
+
* Mirrors the rules `renderCellValue` applies before any formatting — `null`,
|
|
28
|
+
* `undefined`, and a string that is empty or the word `undefined` once the
|
|
29
|
+
* backend's `"X – undefined"` debris is stripped — plus the literal marker
|
|
30
|
+
* itself (whitespace around it aside, which a table cell does not render),
|
|
31
|
+
* since it looks identical on screen and so must read identically.
|
|
32
|
+
*
|
|
33
|
+
* Objects are never missing here: `renderCellValue` renders them (link,
|
|
34
|
+
* name, or escaped JSON).
|
|
35
|
+
*/
|
|
36
|
+
export declare function isMissingCellValue(value: unknown): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Removes the `"Text – undefined"` / `"undefined – Text"` debris some
|
|
39
|
+
* backends concatenate. Shared with `renderCellValue` so both apply the very
|
|
40
|
+
* same cleanup.
|
|
41
|
+
*/
|
|
42
|
+
export declare function stripUndefinedDebris(value: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Whether one CHART data entry is missing: `null` / `undefined`, a non-finite
|
|
45
|
+
* number (Chart.js parses those to `null` too), or a point whose `y` is.
|
|
46
|
+
*/
|
|
47
|
+
export declare function isMissingChartValue(value: unknown): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* What a chart's missing values amount to.
|
|
50
|
+
*
|
|
51
|
+
* Only ENTRIES count: an explicit `null` (or non-finite number, or a point
|
|
52
|
+
* whose `y` is one). A dataset with no entry at all (`data: []`) is not
|
|
53
|
+
* "missing" — it is how 6.23.0 and earlier payloads said "nothing yet", e.g.
|
|
54
|
+
* while streaming, and it keeps rendering exactly as it did then.
|
|
55
|
+
*/
|
|
56
|
+
export interface ChartMissingSummary {
|
|
57
|
+
/** At least one entry of one dataset is missing. */
|
|
58
|
+
hasMissing: boolean;
|
|
59
|
+
/** Per dataset, in order: it has entries and every one of them is missing. */
|
|
60
|
+
fullyMissing: boolean[];
|
|
61
|
+
/**
|
|
62
|
+
* Per dataset, in order: at least one observed value AND at least one
|
|
63
|
+
* missing entry — the series a reader actually sees broken.
|
|
64
|
+
*/
|
|
65
|
+
partiallyMissing: boolean[];
|
|
66
|
+
/** Something is missing and no dataset has a single observed value: nothing to plot. */
|
|
67
|
+
allMissing: boolean;
|
|
68
|
+
}
|
|
69
|
+
interface ChartDataLike {
|
|
70
|
+
data?: {
|
|
71
|
+
datasets?: Array<{
|
|
72
|
+
data?: unknown[];
|
|
73
|
+
} | null | undefined>;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** Summarises the missing values of a chart payload. Never throws on a malformed payload. */
|
|
77
|
+
export declare function summarizeChartMissing(params: ChartDataLike | null | undefined): ChartMissingSummary;
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=missing-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-value.d.ts","sourceRoot":"","sources":["../../src/utils/missing-value.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,6FAA6F;AAC7F,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAIxD,CAAA;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK1D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQ3D;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,UAAU,EAAE,OAAO,CAAA;IACnB,8EAA8E;IAC9E,YAAY,EAAE,OAAO,EAAE,CAAA;IACvB;;;OAGG;IACH,gBAAgB,EAAE,OAAO,EAAE,CAAA;IAC3B,wFAAwF;IACxF,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,CAAC,EAAE,OAAO,EAAE,CAAA;SAAE,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;KAC1D,CAAA;CACF;AAED,6FAA6F;AAC7F,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,mBAAmB,CAyBnG"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const MISSING_VALUE_MARKER = "-";
|
|
2
|
+
const PART_TO_WHOLE_CHART_TYPES = /* @__PURE__ */ new Set([
|
|
3
|
+
"pie",
|
|
4
|
+
"doughnut",
|
|
5
|
+
"polarArea"
|
|
6
|
+
]);
|
|
7
|
+
function isMissingCellValue(value) {
|
|
8
|
+
if (value === null || value === void 0) return true;
|
|
9
|
+
if (typeof value === "object") return false;
|
|
10
|
+
const cleaned = stripUndefinedDebris(String(value)).trim();
|
|
11
|
+
return cleaned === "" || cleaned === MISSING_VALUE_MARKER || cleaned.toLowerCase() === "undefined";
|
|
12
|
+
}
|
|
13
|
+
function stripUndefinedDebris(value) {
|
|
14
|
+
return value.replace(/\s*[–-]\s*undefined\s*$/gi, "").replace(/^undefined\s*[–-]\s*/gi, "");
|
|
15
|
+
}
|
|
16
|
+
function isMissingChartValue(value) {
|
|
17
|
+
if (value === null || value === void 0) return true;
|
|
18
|
+
if (typeof value === "number") return !Number.isFinite(value);
|
|
19
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
20
|
+
const y = value.y;
|
|
21
|
+
return y === null || y === void 0 || typeof y === "number" && !Number.isFinite(y);
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function summarizeChartMissing(params) {
|
|
26
|
+
var _a;
|
|
27
|
+
const datasets = Array.isArray((_a = params == null ? void 0 : params.data) == null ? void 0 : _a.datasets) ? params.data.datasets : [];
|
|
28
|
+
const fullyMissing = [];
|
|
29
|
+
const partiallyMissing = [];
|
|
30
|
+
let anyMissing = false;
|
|
31
|
+
let anyObserved = false;
|
|
32
|
+
for (const dataset of datasets) {
|
|
33
|
+
const data = Array.isArray(dataset == null ? void 0 : dataset.data) ? dataset.data : [];
|
|
34
|
+
let observed = 0;
|
|
35
|
+
let missing = 0;
|
|
36
|
+
for (const value of data) {
|
|
37
|
+
if (isMissingChartValue(value)) missing += 1;
|
|
38
|
+
else observed += 1;
|
|
39
|
+
}
|
|
40
|
+
fullyMissing.push(missing > 0 && observed === 0);
|
|
41
|
+
partiallyMissing.push(observed > 0 && missing > 0);
|
|
42
|
+
anyMissing || (anyMissing = missing > 0);
|
|
43
|
+
anyObserved || (anyObserved = observed > 0);
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
hasMissing: anyMissing,
|
|
47
|
+
fullyMissing,
|
|
48
|
+
partiallyMissing,
|
|
49
|
+
allMissing: anyMissing && !anyObserved
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
MISSING_VALUE_MARKER,
|
|
54
|
+
PART_TO_WHOLE_CHART_TYPES,
|
|
55
|
+
isMissingCellValue,
|
|
56
|
+
isMissingChartValue,
|
|
57
|
+
stripUndefinedDebris,
|
|
58
|
+
summarizeChartMissing
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=missing-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-value.js","sources":["../../src/utils/missing-value.ts"],"sourcesContent":["/**\n * Missing values — one definition shared by tables, chart data views,\n * degraded projections, chart validation and the chart renderer.\n *\n * @since v6.24.0\n *\n * A missing value is a value the payload says EXISTS but was not observed:\n * `null` in a chart dataset (or as a point's `y`), `null` / `undefined` in a\n * table cell. It is not a zero, and it is not the absence of a row or of a\n * label: every view keeps its slot and marks it.\n *\n * Runtime-free on purpose (no `solid-js`): the pure projections in\n * `chart-data-table.ts` and `degraded-projections.ts`, and `validation.ts`\n * (published as the `/validation` subpath), import it.\n */\n\n/** The glyph a table cell shows for a missing value — `renderCellValue`'s historical `-`. */\nexport const MISSING_VALUE_MARKER = '-'\n\n/**\n * Chart types that encode a value as a share of a whole (or, for polar area,\n * as a wedge whose emptiness reads as zero). Chart.js parses a `null` share\n * as `0`, so these types refuse missing values instead of drawing them.\n */\nexport const PART_TO_WHOLE_CHART_TYPES: ReadonlySet<string> = new Set([\n 'pie',\n 'doughnut',\n 'polarArea',\n])\n\n/**\n * Whether a raw TABLE cell value is displayed as {@link MISSING_VALUE_MARKER}.\n *\n * Mirrors the rules `renderCellValue` applies before any formatting — `null`,\n * `undefined`, and a string that is empty or the word `undefined` once the\n * backend's `\"X – undefined\"` debris is stripped — plus the literal marker\n * itself (whitespace around it aside, which a table cell does not render),\n * since it looks identical on screen and so must read identically.\n *\n * Objects are never missing here: `renderCellValue` renders them (link,\n * name, or escaped JSON).\n */\nexport function isMissingCellValue(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'object') return false\n const cleaned = stripUndefinedDebris(String(value)).trim()\n return cleaned === '' || cleaned === MISSING_VALUE_MARKER || cleaned.toLowerCase() === 'undefined'\n}\n\n/**\n * Removes the `\"Text – undefined\"` / `\"undefined – Text\"` debris some\n * backends concatenate. Shared with `renderCellValue` so both apply the very\n * same cleanup.\n */\nexport function stripUndefinedDebris(value: string): string {\n return value.replace(/\\s*[–-]\\s*undefined\\s*$/gi, '').replace(/^undefined\\s*[–-]\\s*/gi, '')\n}\n\n/**\n * Whether one CHART data entry is missing: `null` / `undefined`, a non-finite\n * number (Chart.js parses those to `null` too), or a point whose `y` is.\n */\nexport function isMissingChartValue(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'number') return !Number.isFinite(value)\n if (typeof value === 'object' && !Array.isArray(value)) {\n const y = (value as { y?: unknown }).y\n return y === null || y === undefined || (typeof y === 'number' && !Number.isFinite(y))\n }\n return false\n}\n\n/**\n * What a chart's missing values amount to.\n *\n * Only ENTRIES count: an explicit `null` (or non-finite number, or a point\n * whose `y` is one). A dataset with no entry at all (`data: []`) is not\n * \"missing\" — it is how 6.23.0 and earlier payloads said \"nothing yet\", e.g.\n * while streaming, and it keeps rendering exactly as it did then.\n */\nexport interface ChartMissingSummary {\n /** At least one entry of one dataset is missing. */\n hasMissing: boolean\n /** Per dataset, in order: it has entries and every one of them is missing. */\n fullyMissing: boolean[]\n /**\n * Per dataset, in order: at least one observed value AND at least one\n * missing entry — the series a reader actually sees broken.\n */\n partiallyMissing: boolean[]\n /** Something is missing and no dataset has a single observed value: nothing to plot. */\n allMissing: boolean\n}\n\ninterface ChartDataLike {\n data?: {\n datasets?: Array<{ data?: unknown[] } | null | undefined>\n }\n}\n\n/** Summarises the missing values of a chart payload. Never throws on a malformed payload. */\nexport function summarizeChartMissing(params: ChartDataLike | null | undefined): ChartMissingSummary {\n const datasets = Array.isArray(params?.data?.datasets) ? params.data.datasets : []\n const fullyMissing: boolean[] = []\n const partiallyMissing: boolean[] = []\n let anyMissing = false\n let anyObserved = false\n for (const dataset of datasets) {\n const data = Array.isArray(dataset?.data) ? dataset.data : []\n let observed = 0\n let missing = 0\n for (const value of data) {\n if (isMissingChartValue(value)) missing += 1\n else observed += 1\n }\n fullyMissing.push(missing > 0 && observed === 0)\n partiallyMissing.push(observed > 0 && missing > 0)\n anyMissing ||= missing > 0\n anyObserved ||= observed > 0\n }\n return {\n hasMissing: anyMissing,\n fullyMissing,\n partiallyMissing,\n allMissing: anyMissing && !anyObserved,\n }\n}\n"],"names":[],"mappings":"AAiBO,MAAM,uBAAuB;AAO7B,MAAM,gDAAqD,IAAI;AAAA,EACpE;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAcM,SAAS,mBAAmB,OAAyB;AAC1D,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,qBAAqB,OAAO,KAAK,CAAC,EAAE,KAAA;AACpD,SAAO,YAAY,MAAM,YAAY,wBAAwB,QAAQ,kBAAkB;AACzF;AAOO,SAAS,qBAAqB,OAAuB;AAC1D,SAAO,MAAM,QAAQ,6BAA6B,EAAE,EAAE,QAAQ,0BAA0B,EAAE;AAC5F;AAMO,SAAS,oBAAoB,OAAyB;AAC3D,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,iBAAiB,CAAC,OAAO,SAAS,KAAK;AAC5D,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AACtD,UAAM,IAAK,MAA0B;AACrC,WAAO,MAAM,QAAQ,MAAM,UAAc,OAAO,MAAM,YAAY,CAAC,OAAO,SAAS,CAAC;AAAA,EACtF;AACA,SAAO;AACT;AA+BO,SAAS,sBAAsB,QAA+D;AApF9F;AAqFL,QAAM,WAAW,MAAM,SAAQ,sCAAQ,SAAR,mBAAc,QAAQ,IAAI,OAAO,KAAK,WAAW,CAAA;AAChF,QAAM,eAA0B,CAAA;AAChC,QAAM,mBAA8B,CAAA;AACpC,MAAI,aAAa;AACjB,MAAI,cAAc;AAClB,aAAW,WAAW,UAAU;AAC9B,UAAM,OAAO,MAAM,QAAQ,mCAAS,IAAI,IAAI,QAAQ,OAAO,CAAA;AAC3D,QAAI,WAAW;AACf,QAAI,UAAU;AACd,eAAW,SAAS,MAAM;AACxB,UAAI,oBAAoB,KAAK,EAAG,YAAW;AAAA,UACtC,aAAY;AAAA,IACnB;AACA,iBAAa,KAAK,UAAU,KAAK,aAAa,CAAC;AAC/C,qBAAiB,KAAK,WAAW,KAAK,UAAU,CAAC;AACjD,gCAAe,UAAU;AACzB,kCAAgB,WAAW;AAAA,EAC7B;AACA,SAAO;AAAA,IACL,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,YAAY,cAAc,CAAC;AAAA,EAAA;AAE/B;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seed-ship/mcp-ui-solid",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.24.0",
|
|
4
4
|
"description": "SolidJS components for rendering MCP-generated UI resources",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -44,6 +44,9 @@
|
|
|
44
44
|
],
|
|
45
45
|
"plugins/duckdb": [
|
|
46
46
|
"./dist/plugins/duckdb.d.ts"
|
|
47
|
+
],
|
|
48
|
+
"plugins/katex": [
|
|
49
|
+
"./dist/plugins/katex.d.ts"
|
|
47
50
|
]
|
|
48
51
|
}
|
|
49
52
|
},
|
|
@@ -147,6 +150,17 @@
|
|
|
147
150
|
"default": "./dist/plugins/duckdb.cjs"
|
|
148
151
|
}
|
|
149
152
|
},
|
|
153
|
+
"./plugins/katex": {
|
|
154
|
+
"solid": "./src/plugins/katex.ts",
|
|
155
|
+
"import": {
|
|
156
|
+
"types": "./dist/plugins/katex.d.ts",
|
|
157
|
+
"default": "./dist/plugins/katex.js"
|
|
158
|
+
},
|
|
159
|
+
"require": {
|
|
160
|
+
"types": "./dist/plugins/katex.d.cts",
|
|
161
|
+
"default": "./dist/plugins/katex.cjs"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
150
164
|
"./src/*": "./src/*"
|
|
151
165
|
},
|
|
152
166
|
"_size-limit-note": "size-limit is a regression guardrail, not a hard cap — it flags accidental bundle bloat. It measures the pre-built dist/index.js and sums the FULL graph reachable from each entry, including lazy import() chunks (leaflet, @antv/g6, chart.js) a consumer fetches on demand, NOT at import time — so the figures are worst-case totals, not eager load cost. Since v6.6.0 the 'Streaming renderer' entry delegates to UIResourceRenderer (Gap 1 parity), so its graph equals the full renderer set; its budget is set to 1 MB (generous headroom — the real eager cost is far lower). The 'Hooks only' and 'Full bundle' limits are pre-existing and unchanged by v6.6.0. size-limit is informational only — it does not gate CI.",
|
|
@@ -176,6 +190,7 @@
|
|
|
176
190
|
"chart.js": "^4.0.0",
|
|
177
191
|
"chartjs-plugin-zoom": "^2.0.0",
|
|
178
192
|
"highlight.js": "^11.9.0",
|
|
193
|
+
"katex": "0.18.4",
|
|
179
194
|
"leaflet": "^1.9.4",
|
|
180
195
|
"leaflet.markercluster": "^1.5.0",
|
|
181
196
|
"protomaps-leaflet": "^4.0.0",
|
|
@@ -197,6 +212,9 @@
|
|
|
197
212
|
"highlight.js": {
|
|
198
213
|
"optional": true
|
|
199
214
|
},
|
|
215
|
+
"katex": {
|
|
216
|
+
"optional": true
|
|
217
|
+
},
|
|
200
218
|
"leaflet": {
|
|
201
219
|
"optional": true
|
|
202
220
|
},
|
|
@@ -211,7 +229,7 @@
|
|
|
211
229
|
}
|
|
212
230
|
},
|
|
213
231
|
"dependencies": {
|
|
214
|
-
"@seed-ship/mcp-ui-spec": "^5.
|
|
232
|
+
"@seed-ship/mcp-ui-spec": "^5.7.0",
|
|
215
233
|
"@types/dompurify": "^3.0.5",
|
|
216
234
|
"dompurify": "^3.4.12",
|
|
217
235
|
"marked": "^16.3.0",
|
|
@@ -232,6 +250,7 @@
|
|
|
232
250
|
"chart.js": "^4.5.1",
|
|
233
251
|
"eslint": "^8.56.0",
|
|
234
252
|
"jsdom": "^27.2.0",
|
|
253
|
+
"katex": "0.18.4",
|
|
235
254
|
"leaflet.markercluster": "^1.5.3",
|
|
236
255
|
"size-limit": "^12.0.0",
|
|
237
256
|
"solid-js": "^1.9.11",
|
|
@@ -262,7 +281,7 @@
|
|
|
262
281
|
},
|
|
263
282
|
"scripts": {
|
|
264
283
|
"build": "vite build && pnpm build:types",
|
|
265
|
-
"build:types": "tsc --declaration --emitDeclarationOnly --outDir dist --composite false && pnpm build:types:copy",
|
|
284
|
+
"build:types": "tsc --declaration --emitDeclarationOnly --outDir dist --composite false && pnpm build:types:copy && cp dist/plugins/katex.d.ts dist/plugins/katex.d.cts",
|
|
266
285
|
"build:types:copy": "printf \"export * from './components/index';\\nexport { default } from './components/index';\\n\" > dist/components.d.ts && printf \"export * from './hooks/index';\\n\" > dist/hooks.d.ts && printf \"export * from './types/index';\\n\" > dist/types.d.ts && printf \"export * from './adapters/index';\\n\" > dist/adapters.d.ts && pnpm build:types:cts",
|
|
267
286
|
"build:types:cts": "cp dist/index.d.ts dist/index.d.cts && cp dist/components.d.ts dist/components.d.cts 2>/dev/null || true && cp dist/hooks.d.ts dist/hooks.d.cts 2>/dev/null || true && cp dist/types.d.ts dist/types.d.cts 2>/dev/null || true && cp dist/validation.d.ts dist/validation.d.cts 2>/dev/null || true && cp dist/types-export.d.ts dist/types-export.d.cts 2>/dev/null || true && cp dist/adapters.d.ts dist/adapters.d.cts 2>/dev/null || true && cp dist/adapters/presentation.d.ts dist/adapters/presentation.d.cts 2>/dev/null || true && cp dist/plugins/duckdb.d.ts dist/plugins/duckdb.d.cts 2>/dev/null || true",
|
|
268
287
|
"dev": "vite build --watch",
|
|
@@ -270,7 +289,7 @@
|
|
|
270
289
|
"test:watch": "vitest",
|
|
271
290
|
"test:browser": "vitest --mode browser",
|
|
272
291
|
"lint": "eslint src",
|
|
273
|
-
"typecheck": "tsc --noEmit",
|
|
292
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.contracts.json && tsc --noEmit -p tsconfig.examples.json",
|
|
274
293
|
"clean": "rm -rf dist",
|
|
275
294
|
"size": "size-limit",
|
|
276
295
|
"size:analyze": "size-limit --why"
|