wiki-formant 0.89.1 → 0.89.4
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 +2 -2
- package/dist/base.css +3 -3
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.js +4 -0
- package/dist/react.js +8 -2
- package/dist/stats.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1011,8 +1011,8 @@ total, a rate's mean), every non-empty
|
|
|
1011
1011
|
ranked list, and `?days=` links between windows, all time among them, pinned in
|
|
1012
1012
|
the chart's frame as its own buttons are (`TimeChart`'s `controls`). Each
|
|
1013
1013
|
figure is a button that charts it: visitors, page views, bounce rate,
|
|
1014
|
-
visit length and clicks to X. Visitors count agents; `?agents=apart`, a
|
|
1015
|
-
|
|
1014
|
+
visit length and clicks to X. Visitors count agents; `?agents=apart`, a switch
|
|
1015
|
+
beside the windows, splits them into people and agents, and every
|
|
1016
1016
|
other link on the page keeps the choice. `digest`'s `by_day` carries every
|
|
1017
1017
|
one of those per UTC day, a visit on the day it began, so the days add up to the
|
|
1018
1018
|
totals. A day with no visits has no bounce rate or visit length and is left out
|
package/dist/base.css
CHANGED
|
@@ -294,7 +294,7 @@ html[data-sidebar='closed'] .wiki-sidebar { width: 0; }
|
|
|
294
294
|
.chart-controls { font-size: 0.625rem; }
|
|
295
295
|
.chart-controls :is(button, a) { border: 1px solid var(--ui-border); border-radius: calc(var(--ui-radius) / 2); opacity: 1; transition: background-color 150ms, color 150ms; }
|
|
296
296
|
.chart-controls :is(button, a):hover { background: var(--ui-surface-2); }
|
|
297
|
-
.chart-controls :is(button, a):is([aria-pressed='true'], [aria-current]) { background: var(--ui-accent); border-color: var(--ui-accent); color: var(--ui-on-accent); }
|
|
297
|
+
.chart-controls :is(button, a):is([aria-pressed='true'], [aria-checked='true'], [aria-current]) { background: var(--ui-accent); border-color: var(--ui-accent); color: var(--ui-on-accent); }
|
|
298
298
|
|
|
299
299
|
.code-tabs { margin-block: 1rem; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); }
|
|
300
300
|
.code-tabs-list { overflow-x: auto; border-bottom: 1px solid var(--ui-border); background: var(--ui-surface); }
|
|
@@ -618,8 +618,8 @@ pre:hover > .code-copy-btn,
|
|
|
618
618
|
.chart-controls :is(button, a) { padding: 0.125rem 0.375rem; font: inherit; color: inherit; text-decoration: none; background: none; cursor: pointer; opacity: 0.6; }
|
|
619
619
|
/* An icon sits on the text's line, so an icon button is as tall as a labelled one. */
|
|
620
620
|
.chart-icon { display: inline-block; width: 1em; height: 1em; vertical-align: -0.125em; }
|
|
621
|
-
/* A button is pressed
|
|
622
|
-
.chart-controls :is(button, a):is([aria-pressed='true'], [aria-current]) { opacity: 1; }
|
|
621
|
+
/* A button is pressed, a switch on, and a link (a stats page's window) the page shown. */
|
|
622
|
+
.chart-controls :is(button, a):is([aria-pressed='true'], [aria-checked='true'], [aria-current]) { opacity: 1; }
|
|
623
623
|
/* A step the range cannot make stays in its place, and dims. */
|
|
624
624
|
.chart-controls button:disabled { opacity: 0.3; cursor: default; pointer-events: none; }
|
|
625
625
|
|
package/dist/mcp.d.ts
CHANGED
|
@@ -51,7 +51,8 @@ export type JsonSchema = {
|
|
|
51
51
|
[keyword: string]: unknown;
|
|
52
52
|
};
|
|
53
53
|
export type ToolParam = {
|
|
54
|
-
|
|
54
|
+
/** Unset for a union (`oneOf`, `anyOf`), which the handler checks itself. */
|
|
55
|
+
type?: 'string' | 'number' | 'boolean' | 'array' | 'object';
|
|
55
56
|
description: string;
|
|
56
57
|
enum?: string[];
|
|
57
58
|
items?: JsonSchema;
|
package/dist/mcp.js
CHANGED
|
@@ -242,6 +242,10 @@ function validateArgs(tool, args) {
|
|
|
242
242
|
problems.push(`Parameter "${key}" must contain only ${itemType}s.`);
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
|
+
else if (!spec.type) {
|
|
246
|
+
// No one type (a `oneOf` of shapes, as a zod union emits) is the tool's own
|
|
247
|
+
// to check, as with array items: compared to undefined, every call was refused.
|
|
248
|
+
}
|
|
245
249
|
else if (actual !== spec.type) {
|
|
246
250
|
problems.push(`Parameter "${key}" must be a ${spec.type}; received ${actual} (${JSON.stringify(value)}).`);
|
|
247
251
|
}
|
package/dist/react.js
CHANGED
|
@@ -96,10 +96,16 @@ function useCollapsibleSidebar(options = {}) {
|
|
|
96
96
|
}, [storageKey]);
|
|
97
97
|
const toggle = useCallback(() => setOpen(!open), [open, setOpen]);
|
|
98
98
|
// One source of truth either side of hydration: the boot script writes this
|
|
99
|
-
// attribute before first paint, and
|
|
99
|
+
// attribute before first paint, and once storage has been read the hook owns
|
|
100
|
+
// it. Not before: this effect runs in the same commit as the read above, with
|
|
101
|
+
// `open` still the server's `true`, and writing "open" there over a stamped
|
|
102
|
+
// "closed" widened a remembered-closed rail for one frame and then slid it
|
|
103
|
+
// shut — the very slide the boot script exists to prevent.
|
|
100
104
|
useEffect(() => {
|
|
105
|
+
if (!ready)
|
|
106
|
+
return;
|
|
101
107
|
document.documentElement.setAttribute(SIDEBAR_ATTRIBUTE, open ? 'open' : 'closed');
|
|
102
|
-
}, [open]);
|
|
108
|
+
}, [open, ready]);
|
|
103
109
|
return { open, setOpen, toggle, isMobile, ready };
|
|
104
110
|
}
|
|
105
111
|
// ---- sharing that state across the layout -----------------------------------
|
package/dist/stats.js
CHANGED
|
@@ -72,8 +72,8 @@ export function Stats({ digest: d, days, filter = {}, apart = false, ranges = ST
|
|
|
72
72
|
const at = (f, n = days, a = apart) => href(n, f, a);
|
|
73
73
|
const to = (k) => (v) => at({ ...filter, [k]: v });
|
|
74
74
|
// Each window is another digest, so a link rather than a button, pinned
|
|
75
|
-
// with the chart's own controls, and so is
|
|
76
|
-
const controls = (_jsxs(_Fragment, { children: [_jsx("div", { role: "group", "aria-label": "Window", children: ranges.map(n => (_jsx("a", { href: at(filter, n), "aria-current": n === days ? 'page' : undefined, children: windowLabel(n) }, n))) }),
|
|
75
|
+
// with the chart's own controls, and so is the switch that counts agents apart.
|
|
76
|
+
const controls = (_jsxs(_Fragment, { children: [_jsx("div", { role: "group", "aria-label": "Window", children: ranges.map(n => (_jsx("a", { href: at(filter, n), "aria-current": n === days ? 'page' : undefined, children: windowLabel(n) }, n))) }), _jsx("div", { children: _jsx("a", { href: at(filter, days, !apart), role: "switch", "aria-checked": apart, title: "People and agents counted apart", children: "Agents apart" }) })] }));
|
|
77
77
|
return (_jsxs("div", { className: "stats", children: [narrowed.length > 0 && (_jsxs("div", { className: "stats-filters", children: [_jsx("ul", { "aria-label": "Narrowed to", children: narrowed.map(k => (_jsx("li", { children: _jsxs("a", { href: at({ ...filter, [k]: undefined }), title: "Remove", children: [NAMES[k], ": ", k === 'country' ? country(filter[k]) : filter[k], " \u00D7"] }) }, k))) }), start < counted && d.counted_from && (_jsxs("p", { children: ["Narrowed figures start on ", d.counted_from, ", the first day this site counted its own visits."] }))] })), _jsx(StatsFigures, { digest: d, first: first, apart: apart, controls: controls }), _jsxs("div", { className: "stats-lists", children: [_jsx(StatsList, { title: "Pages", rows: rows(d.top_pages, 'page', 'visitors'), to: to('page') }), _jsx(StatsList, { title: "Entry pages", rows: rows(d.entry_pages, 'page', 'visitors'), to: to('entry') }), _jsx(StatsList, { title: "Sources", rows: rows(d.top_sources, 'source', 'visitors'), to: to('source') }), _jsx(StatsList, { title: "From X posts", rows: rows(d.from_posts, 'page', 'visitors'), to: v => at({ ...filter, source: 'x', entry: v }) }), _jsx(StatsList, { title: "Sibling sites", rows: rows(d.sibling_referrals, 'source', 'visitors'), to: to('source') }), _jsx(StatsList, { title: "Countries", rows: rows(d.countries, 'country', 'visitors'), label: country, to: to('country') }), _jsx(StatsList, { title: "Devices", rows: rows(d.devices, 'device', 'visitors'), to: to('device') }), _jsx(StatsList, { title: "Agents", rows: rows(d.top_agents, 'agent', 'visitors') }), _jsx(StatsList, { title: "Agent tool calls", rows: rows(d.agent_tool_calls, 'tool', 'events') }), _jsx(StatsList, { title: "Searches that found nothing", rows: rows(d.gaps, 'query', 'events') })] })] }));
|
|
78
78
|
}
|
|
79
79
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wiki-formant",
|
|
3
|
-
"version": "0.89.
|
|
3
|
+
"version": "0.89.4",
|
|
4
4
|
"description": "The portable half of a wiki: derived taxonomy and facet controls, a version-negotiating MCP transport, markdown twins, block rendering, a rich-text editor engine, conditional-GET plumbing, and the headers and CSP every origin sends.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|