@book.dev/sdk 3.16.0 → 3.17.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/dist/ai.d.ts +1 -1
- package/dist/assetUpload.d.ts +28 -0
- package/dist/assetUpload.js +54 -0
- package/dist/assetUpload.js.map +1 -0
- package/dist/blockCatalogue.d.ts +15 -39
- package/dist/blockCatalogue.js +30 -52
- package/dist/blockCatalogue.js.map +1 -1
- package/dist/blockPropSchemas.d.ts +293 -0
- package/dist/blockPropSchemas.js +77 -0
- package/dist/blockPropSchemas.js.map +1 -0
- package/dist/blockSnapshot.d.ts +48 -0
- package/dist/blockSnapshot.js +211 -0
- package/dist/blockSnapshot.js.map +1 -0
- package/dist/content.d.ts +5 -4
- package/dist/content.js +2 -1
- package/dist/content.js.map +1 -1
- package/dist/databaseTools.d.ts +86 -0
- package/dist/databaseTools.js +174 -0
- package/dist/databaseTools.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/pageTools.d.ts +61 -0
- package/dist/pageTools.js +175 -0
- package/dist/pageTools.js.map +1 -0
- package/dist/richTextInput.d.ts +29 -0
- package/dist/richTextInput.js +142 -0
- package/dist/richTextInput.js.map +1 -0
- package/dist/suggestions.d.ts +1 -1
- package/dist/tableSnapshot.d.ts +12 -4
- package/dist/tableSnapshot.js +34 -4
- package/dist/tableSnapshot.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { BACKLINKS_PROPERTY_ID, COVER_PROPERTY_ID, FULLWIDTH_PROPERTY_ID, ICON_PROPERTY_ID, OWNER_PROPERTY_ID, THEME_PROPERTY_ID, VERIFICATION_PROPERTY_ID, } from './pageProperties';
|
|
2
|
+
export const PAGE_THEME_IDS = [
|
|
3
|
+
'default', 'amber', 'forest', 'graphite', 'ocean', 'rose', 'sandstone', 'slate', 'sunset', 'teal', 'violet',
|
|
4
|
+
];
|
|
5
|
+
export const PAGE_BACKGROUND_TOKENS = ['gray', 'red', 'orange', 'yellow', 'green', 'blue', 'purple', 'pink'];
|
|
6
|
+
export const PAGE_COVER_GRADIENT_IDS = ['dawn', 'ocean', 'dusk', 'forest', 'ember', 'slate', 'citrus', 'mint', 'grape', 'sand', 'rose', 'night'];
|
|
7
|
+
export const COVER_GRADIENTS = [
|
|
8
|
+
{ id: 'dawn', css: 'linear-gradient(120deg, #f6d365 0%, #fda085 100%)' },
|
|
9
|
+
{ id: 'ocean', css: 'linear-gradient(120deg, #4facfe 0%, #00f2fe 100%)' },
|
|
10
|
+
{ id: 'dusk', css: 'linear-gradient(120deg, #a18cd1 0%, #fbc2eb 100%)' },
|
|
11
|
+
{ id: 'forest', css: 'linear-gradient(120deg, #0ba360 0%, #3cba92 100%)' },
|
|
12
|
+
{ id: 'ember', css: 'linear-gradient(120deg, #ff6a88 0%, #ff99ac 60%, #ffc3a0 100%)' },
|
|
13
|
+
{ id: 'slate', css: 'linear-gradient(120deg, #2b5876 0%, #4e4376 100%)' },
|
|
14
|
+
{ id: 'citrus', css: 'linear-gradient(120deg, #f7971e 0%, #ffd200 100%)' },
|
|
15
|
+
{ id: 'mint', css: 'linear-gradient(120deg, #43e97b 0%, #38f9d7 100%)' },
|
|
16
|
+
{ id: 'grape', css: 'linear-gradient(120deg, #667eea 0%, #764ba2 100%)' },
|
|
17
|
+
{ id: 'sand', css: 'linear-gradient(120deg, #e6dada 0%, #d3a17b 100%)' },
|
|
18
|
+
{ id: 'rose', css: 'linear-gradient(120deg, #ee9ca7 0%, #ffdde1 100%)' },
|
|
19
|
+
{ id: 'night', css: 'linear-gradient(120deg, #232526 0%, #414345 100%)' },
|
|
20
|
+
];
|
|
21
|
+
export class PageToolError extends Error {
|
|
22
|
+
constructor(code, message) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.code = code;
|
|
25
|
+
this.name = 'PageToolError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const record = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : null;
|
|
29
|
+
const oneOf = (value, values) => typeof value === 'string' && values.includes(value);
|
|
30
|
+
/** Validate and project the public appearance input onto reserved page-property ids. */
|
|
31
|
+
export function buildPageAppearancePatch(input) {
|
|
32
|
+
const patch = {};
|
|
33
|
+
if (input.icon !== undefined) {
|
|
34
|
+
if (input.icon !== null && (typeof input.icon !== 'string' || input.icon.length > 32))
|
|
35
|
+
throw new PageToolError('invalid_input', 'icon must be a string of at most 32 characters or null.');
|
|
36
|
+
patch[ICON_PROPERTY_ID] = input.icon;
|
|
37
|
+
}
|
|
38
|
+
if (input.fullWidth !== undefined) {
|
|
39
|
+
if (input.fullWidth !== null && typeof input.fullWidth !== 'boolean')
|
|
40
|
+
throw new PageToolError('invalid_input', 'fullWidth must be a boolean or null.');
|
|
41
|
+
patch[FULLWIDTH_PROPERTY_ID] = input.fullWidth;
|
|
42
|
+
}
|
|
43
|
+
if (input.theme !== undefined) {
|
|
44
|
+
if (input.theme === null)
|
|
45
|
+
patch[THEME_PROPERTY_ID] = null;
|
|
46
|
+
else {
|
|
47
|
+
const theme = record(input.theme);
|
|
48
|
+
if (!theme)
|
|
49
|
+
throw new PageToolError('invalid_input', 'theme must be an object or null.');
|
|
50
|
+
const allowed = new Set(['themeId', 'background', 'controlIntensity', 'interfaceIntensity']);
|
|
51
|
+
if (Object.keys(theme).some((key) => !allowed.has(key)))
|
|
52
|
+
throw new PageToolError('invalid_input', 'theme contains an unknown setting.');
|
|
53
|
+
if (theme.themeId !== undefined && !oneOf(theme.themeId, PAGE_THEME_IDS))
|
|
54
|
+
throw new PageToolError('invalid_input', `Unknown theme "${String(theme.themeId)}".`);
|
|
55
|
+
if (theme.background !== undefined && !oneOf(theme.background, PAGE_BACKGROUND_TOKENS))
|
|
56
|
+
throw new PageToolError('invalid_input', `Unknown background "${String(theme.background)}".`);
|
|
57
|
+
for (const key of ['controlIntensity', 'interfaceIntensity']) {
|
|
58
|
+
if (theme[key] !== undefined && (!Number.isInteger(theme[key]) || Number(theme[key]) < 0 || Number(theme[key]) > 3))
|
|
59
|
+
throw new PageToolError('invalid_input', `${key} must be an integer from 0 to 3.`);
|
|
60
|
+
}
|
|
61
|
+
patch[THEME_PROPERTY_ID] = theme;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (input.cover !== undefined) {
|
|
65
|
+
if (input.cover === null)
|
|
66
|
+
patch[COVER_PROPERTY_ID] = null;
|
|
67
|
+
else {
|
|
68
|
+
const cover = record(input.cover);
|
|
69
|
+
if (!cover || (cover.kind !== 'gradient' && cover.kind !== 'image'))
|
|
70
|
+
throw new PageToolError('invalid_input', 'cover must be a gradient or image cover.');
|
|
71
|
+
const allowed = cover.kind === 'gradient' ? new Set(['kind', 'gradientId']) : new Set(['kind', 'url', 'position']);
|
|
72
|
+
if (Object.keys(cover).some((key) => !allowed.has(key)))
|
|
73
|
+
throw new PageToolError('invalid_input', 'cover contains an unknown setting.');
|
|
74
|
+
if (cover.kind === 'gradient' && !oneOf(cover.gradientId, PAGE_COVER_GRADIENT_IDS))
|
|
75
|
+
throw new PageToolError('invalid_input', 'A gradient cover requires a valid gradientId.');
|
|
76
|
+
if (cover.kind === 'image' && (typeof cover.url !== 'string' || (!/^https:\/\//i.test(cover.url) && !cover.url.startsWith('/api/assets/')))) {
|
|
77
|
+
throw new PageToolError('invalid_input', 'cover.url must be https or an OpenBook asset URL');
|
|
78
|
+
}
|
|
79
|
+
if (cover.position !== undefined && (typeof cover.position !== 'number' || cover.position < 0 || cover.position > 1))
|
|
80
|
+
throw new PageToolError('invalid_input', 'cover.position must be between 0 and 1.');
|
|
81
|
+
patch[COVER_PROPERTY_ID] = cover.kind === 'gradient'
|
|
82
|
+
? { kind: 'gradient', css: COVER_GRADIENTS.find(({ id }) => id === cover.gradientId).css }
|
|
83
|
+
: cover;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (Object.keys(patch).length === 0)
|
|
87
|
+
throw new PageToolError('invalid_input', 'Pass at least one appearance setting.');
|
|
88
|
+
return patch;
|
|
89
|
+
}
|
|
90
|
+
export function validatePageProperties(input) {
|
|
91
|
+
const out = {};
|
|
92
|
+
for (const [key, value] of Object.entries(input)) {
|
|
93
|
+
if (key === BACKLINKS_PROPERTY_ID)
|
|
94
|
+
throw new PageToolError('invalid_input', 'Backlinks are computed and cannot be set.');
|
|
95
|
+
if (key === OWNER_PROPERTY_ID) {
|
|
96
|
+
if (value !== null && typeof value !== 'string')
|
|
97
|
+
throw new PageToolError('invalid_input', 'sys_owner must be a string or null.');
|
|
98
|
+
}
|
|
99
|
+
else if (key === VERIFICATION_PROPERTY_ID) {
|
|
100
|
+
if (value !== null) {
|
|
101
|
+
const v = record(value);
|
|
102
|
+
if (!v || typeof v.verified !== 'boolean' || ['by', 'at', 'expiresAt'].some((field) => v[field] !== undefined && v[field] !== null && typeof v[field] !== 'string')) {
|
|
103
|
+
throw new PageToolError('invalid_input', 'sys_verification has an invalid value.');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
throw new PageToolError('invalid_input', `Unknown page property "${key}".`);
|
|
109
|
+
}
|
|
110
|
+
out[key] = value;
|
|
111
|
+
}
|
|
112
|
+
if (Object.keys(out).length === 0)
|
|
113
|
+
throw new PageToolError('invalid_input', 'Pass at least one page property.');
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
const page = async (store, pageId) => {
|
|
117
|
+
const found = await store.getPage(pageId);
|
|
118
|
+
if (!found)
|
|
119
|
+
throw new PageToolError('page_not_found', 'Page not found.');
|
|
120
|
+
return found;
|
|
121
|
+
};
|
|
122
|
+
export async function setPageAppearanceTool(store, pageId, input) {
|
|
123
|
+
await page(store, pageId);
|
|
124
|
+
const updated = await store.setPageProperties(pageId, buildPageAppearancePatch(input));
|
|
125
|
+
if (!updated)
|
|
126
|
+
throw new PageToolError('page_not_found', 'Page not found.');
|
|
127
|
+
return updated;
|
|
128
|
+
}
|
|
129
|
+
export async function getPagePropertiesTool(store, pageId) {
|
|
130
|
+
return (await page(store, pageId)).properties ?? {};
|
|
131
|
+
}
|
|
132
|
+
export async function setPagePropertiesTool(store, pageId, properties) {
|
|
133
|
+
await page(store, pageId);
|
|
134
|
+
const updated = await store.setPageProperties(pageId, validatePageProperties(properties));
|
|
135
|
+
if (!updated)
|
|
136
|
+
throw new PageToolError('page_not_found', 'Page not found.');
|
|
137
|
+
return updated;
|
|
138
|
+
}
|
|
139
|
+
/** Validate a page move and compute the ordered destination siblings without writing. */
|
|
140
|
+
export function buildMovePlan(pages, input) {
|
|
141
|
+
if (!pages.some((candidate) => candidate.id === input.pageId))
|
|
142
|
+
throw new PageToolError('page_not_found', 'Page not found.');
|
|
143
|
+
if (input.parentId === input.pageId)
|
|
144
|
+
throw new PageToolError('invalid_move', 'A page cannot be its own parent.');
|
|
145
|
+
if (input.parentId !== null && !pages.some((candidate) => candidate.id === input.parentId))
|
|
146
|
+
throw new PageToolError('parent_not_found', 'Parent page not found.');
|
|
147
|
+
const byId = new Map(pages.map((candidate) => [candidate.id, candidate]));
|
|
148
|
+
for (let ancestor = input.parentId; ancestor !== null; ancestor = byId.get(ancestor)?.parentId ?? null) {
|
|
149
|
+
if (ancestor === input.pageId)
|
|
150
|
+
throw new PageToolError('invalid_move', 'The move would create a cycle.');
|
|
151
|
+
}
|
|
152
|
+
const siblings = pages.filter((candidate) => candidate.id !== input.pageId && (candidate.parentId ?? null) === input.parentId).map(({ id }) => id);
|
|
153
|
+
if (input.position && 'afterId' in input.position) {
|
|
154
|
+
const at = siblings.indexOf(input.position.afterId);
|
|
155
|
+
if (at < 0)
|
|
156
|
+
throw new PageToolError('invalid_input', 'afterId must name a sibling under the destination parent.');
|
|
157
|
+
siblings.splice(at + 1, 0, input.pageId);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
const index = input.position && 'index' in input.position ? input.position.index : siblings.length;
|
|
161
|
+
if (!Number.isInteger(index) || index < 0 || index > siblings.length)
|
|
162
|
+
throw new PageToolError('invalid_input', 'position.index is outside the destination sibling range.');
|
|
163
|
+
siblings.splice(index, 0, input.pageId);
|
|
164
|
+
}
|
|
165
|
+
return { parentId: input.parentId, orderedIds: siblings };
|
|
166
|
+
}
|
|
167
|
+
export async function movePageTool(store, input) {
|
|
168
|
+
await page(store, input.pageId);
|
|
169
|
+
const move = buildMovePlan(await store.listPages(), input);
|
|
170
|
+
const moved = await store.movePage(input.pageId, move);
|
|
171
|
+
if (!moved)
|
|
172
|
+
throw new PageToolError('invalid_move', 'The move was refused.');
|
|
173
|
+
return moved;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=pageTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pageTools.js","sourceRoot":"","sources":["../src/pageTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Inline attributes supported by agent/MCP rich-text input. */
|
|
2
|
+
export interface RunAttrs extends Record<string, unknown> {
|
|
3
|
+
b?: true;
|
|
4
|
+
i?: true;
|
|
5
|
+
u?: true;
|
|
6
|
+
s?: true;
|
|
7
|
+
c?: true;
|
|
8
|
+
a?: string;
|
|
9
|
+
}
|
|
10
|
+
/** The editor's JSON-projection run shape. */
|
|
11
|
+
export interface Run {
|
|
12
|
+
t: string;
|
|
13
|
+
a?: RunAttrs;
|
|
14
|
+
}
|
|
15
|
+
export type RichTextInput = string | {
|
|
16
|
+
runs: Run[];
|
|
17
|
+
};
|
|
18
|
+
export type RichTextInputErrorCode = 'invalid-runs' | 'unsafe-link';
|
|
19
|
+
/** A machine-readable rich-text validation failure. */
|
|
20
|
+
export declare class RichTextInputError extends Error {
|
|
21
|
+
readonly code: RichTextInputErrorCode;
|
|
22
|
+
constructor(code: RichTextInputErrorCode, message: string);
|
|
23
|
+
}
|
|
24
|
+
/** Validate, copy, and coalesce editor-projection runs supplied by a client. */
|
|
25
|
+
export declare function normalizeRuns(input: unknown): Run[];
|
|
26
|
+
/** Parse the deliberately small, DOM-free markdown subset accepted by write tools. */
|
|
27
|
+
export declare function parseMiniMarkdown(text: string): Run[];
|
|
28
|
+
/** Resolve either mini-markdown/plain text or an explicit run envelope. */
|
|
29
|
+
export declare function richTextRuns(input: RichTextInput, plain?: boolean): Run[];
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { isSafeHref } from './bookfile';
|
|
3
|
+
/** A machine-readable rich-text validation failure. */
|
|
4
|
+
export class RichTextInputError extends Error {
|
|
5
|
+
constructor(code, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.name = 'RichTextInputError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const attrsSchema = z.object({
|
|
12
|
+
b: z.literal(true).optional(),
|
|
13
|
+
i: z.literal(true).optional(),
|
|
14
|
+
u: z.literal(true).optional(),
|
|
15
|
+
s: z.literal(true).optional(),
|
|
16
|
+
c: z.literal(true).optional(),
|
|
17
|
+
a: z.string().optional(),
|
|
18
|
+
}).strict();
|
|
19
|
+
const runSchema = z.object({ t: z.string(), a: attrsSchema.optional() }).strict();
|
|
20
|
+
const safeLink = (href) => href.trim() !== '' && isSafeHref(href);
|
|
21
|
+
const sameAttrs = (a, b) => JSON.stringify(a ?? {}) === JSON.stringify(b ?? {});
|
|
22
|
+
/** Validate, copy, and coalesce editor-projection runs supplied by a client. */
|
|
23
|
+
export function normalizeRuns(input) {
|
|
24
|
+
const parsed = z.array(runSchema).safeParse(input);
|
|
25
|
+
if (!parsed.success) {
|
|
26
|
+
throw new RichTextInputError('invalid-runs', `Invalid rich-text runs: ${parsed.error.issues.map((issue) => issue.message).join('; ')}`);
|
|
27
|
+
}
|
|
28
|
+
const out = [];
|
|
29
|
+
for (const raw of parsed.data) {
|
|
30
|
+
if (raw.a?.a && !safeLink(raw.a.a)) {
|
|
31
|
+
throw new RichTextInputError('unsafe-link', `Unsafe link scheme in "${raw.a.a}"; use https, http, or mailto.`);
|
|
32
|
+
}
|
|
33
|
+
if (!raw.t)
|
|
34
|
+
continue;
|
|
35
|
+
const attrs = raw.a && Object.keys(raw.a).length > 0 ? raw.a : undefined;
|
|
36
|
+
const run = attrs ? { t: raw.t, a: attrs } : { t: raw.t };
|
|
37
|
+
const previous = out[out.length - 1];
|
|
38
|
+
if (previous && sameAttrs(previous.a, run.a))
|
|
39
|
+
previous.t += run.t;
|
|
40
|
+
else
|
|
41
|
+
out.push(run);
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
const MARKERS = [
|
|
46
|
+
{ token: '**', attr: 'b' },
|
|
47
|
+
{ token: '~~', attr: 's' },
|
|
48
|
+
{ token: '`', attr: 'c' },
|
|
49
|
+
{ token: '*', attr: 'i' },
|
|
50
|
+
{ token: '_', attr: 'i' },
|
|
51
|
+
];
|
|
52
|
+
const closingAt = (text, token, from) => {
|
|
53
|
+
for (let i = from; i <= text.length - token.length; i += 1) {
|
|
54
|
+
if (text[i] === '\\') {
|
|
55
|
+
i += 1;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// In `**bold *italic***`, the first star in the closing triple belongs to
|
|
59
|
+
// the inner italic span; the final two close the outer bold span.
|
|
60
|
+
if (token === '**' && text.startsWith('***', i))
|
|
61
|
+
return i + 1;
|
|
62
|
+
if (token === '_' && /[\p{L}\p{N}]/u.test(text[i + token.length] ?? ''))
|
|
63
|
+
continue;
|
|
64
|
+
if (text.startsWith(token, i))
|
|
65
|
+
return i;
|
|
66
|
+
}
|
|
67
|
+
return -1;
|
|
68
|
+
};
|
|
69
|
+
const withAttr = (runs, attr, value) => runs.map((run) => ({ ...run, a: { ...run.a, [attr]: value } }));
|
|
70
|
+
const parseRange = (source) => {
|
|
71
|
+
const runs = [];
|
|
72
|
+
let literal = '';
|
|
73
|
+
const flush = () => {
|
|
74
|
+
if (literal)
|
|
75
|
+
runs.push({ t: literal });
|
|
76
|
+
literal = '';
|
|
77
|
+
};
|
|
78
|
+
for (let i = 0; i < source.length;) {
|
|
79
|
+
if (source[i] === '\\' && i + 1 < source.length && /[\\*_[\]()`~]/.test(source[i + 1])) {
|
|
80
|
+
literal += source[i + 1];
|
|
81
|
+
i += 2;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (source[i] === '[') {
|
|
85
|
+
const labelEnd = closingAt(source, ']', i + 1);
|
|
86
|
+
if (labelEnd >= 0 && source[labelEnd + 1] === '(') {
|
|
87
|
+
const urlEnd = closingAt(source, ')', labelEnd + 2);
|
|
88
|
+
if (urlEnd >= 0) {
|
|
89
|
+
let href = source.slice(labelEnd + 2, urlEnd).trim();
|
|
90
|
+
const title = /\s+(?:"[^"]*"|'[^']*')$/.exec(href);
|
|
91
|
+
if (title)
|
|
92
|
+
href = href.slice(0, title.index).trim();
|
|
93
|
+
if (safeLink(href) && !/\s/u.test(href)) {
|
|
94
|
+
flush();
|
|
95
|
+
runs.push(...withAttr(parseRange(source.slice(i + 1, labelEnd)), 'a', href));
|
|
96
|
+
i = urlEnd + 1;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (/^[a-z][a-z0-9+.-]*:/iu.test(href)) {
|
|
100
|
+
throw new RichTextInputError('unsafe-link', `Unsafe link scheme in "${href}"; use https, http, or mailto.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (source[i] === '_' && (source[i - 1] === '_' || source[i + 1] === '_')) {
|
|
106
|
+
literal += source[i];
|
|
107
|
+
i += 1;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const leftOk = i === 0 || !/[\p{L}\p{N}]/u.test(source[i - 1]);
|
|
111
|
+
const marker = MARKERS.find(({ token }) => source.startsWith(token, i) && (token !== '_' || leftOk));
|
|
112
|
+
if (marker) {
|
|
113
|
+
const end = closingAt(source, marker.token, i + marker.token.length);
|
|
114
|
+
if (end >= 0 && end > i + marker.token.length) {
|
|
115
|
+
flush();
|
|
116
|
+
if (marker.token === '`') {
|
|
117
|
+
runs.push({ t: source.slice(i + 1, end), a: { c: true } });
|
|
118
|
+
i = end + 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
runs.push(...withAttr(parseRange(source.slice(i + marker.token.length, end)), marker.attr, true));
|
|
122
|
+
i = end + marker.token.length;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
literal += source[i];
|
|
127
|
+
i += 1;
|
|
128
|
+
}
|
|
129
|
+
flush();
|
|
130
|
+
return normalizeRuns(runs);
|
|
131
|
+
};
|
|
132
|
+
/** Parse the deliberately small, DOM-free markdown subset accepted by write tools. */
|
|
133
|
+
export function parseMiniMarkdown(text) {
|
|
134
|
+
return text ? parseRange(text) : [];
|
|
135
|
+
}
|
|
136
|
+
/** Resolve either mini-markdown/plain text or an explicit run envelope. */
|
|
137
|
+
export function richTextRuns(input, plain = false) {
|
|
138
|
+
if (typeof input === 'string')
|
|
139
|
+
return plain ? (input ? [{ t: input }] : []) : parseMiniMarkdown(input);
|
|
140
|
+
return normalizeRuns(input.runs);
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=richTextInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"richTextInput.js","sourceRoot":"","sources":["../src/richTextInput.ts"],"names":[],"mappings":"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"}
|
package/dist/suggestions.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export interface AuthoredIdentity {
|
|
|
62
62
|
* them into ten kinds would buy the reviewer nothing and force every
|
|
63
63
|
* `Record<SuggestionKind, …>` in the UI to grow ten entries.
|
|
64
64
|
*/
|
|
65
|
-
export type SuggestionKind = 'replace-text' | 'set-cell' | 'insert' | 'delete' | 'set-theme' | 'table-op';
|
|
65
|
+
export type SuggestionKind = 'replace-text' | 'set-cell' | 'insert' | 'move' | 'delete' | 'set-theme' | 'table-op' | 'database-op' | 'page-op';
|
|
66
66
|
/** Lifecycle of a suggestion. */
|
|
67
67
|
export type SuggestionStatus = 'open' | 'accepted' | 'rejected';
|
|
68
68
|
/**
|
package/dist/tableSnapshot.d.ts
CHANGED
|
@@ -37,10 +37,13 @@
|
|
|
37
37
|
* the projection.
|
|
38
38
|
*/
|
|
39
39
|
import type { PageSnapshot } from './types';
|
|
40
|
+
import { type RichTextInput } from './richTextInput';
|
|
40
41
|
/** Prefix of the column-registry entries in a table block's props. */
|
|
41
42
|
export declare const TABLE_COL_PREFIX = "col:";
|
|
42
43
|
/** Prefix of the per-column colour entries (`colbg:<colId>` → palette token). */
|
|
43
44
|
export declare const TABLE_COLBG_PREFIX = "colbg:";
|
|
45
|
+
export declare const TABLE_COLW_PREFIX = "colw:";
|
|
46
|
+
export declare const TABLE_COLUMN_MIN_WIDTH = 48;
|
|
44
47
|
/**
|
|
45
48
|
* The table order-contract PRIVATE keys (TBL-1): `row.props.ord`,
|
|
46
49
|
* `cell.props.col`, the `col:<id>` column registry, and the `colbg:<id>`
|
|
@@ -71,7 +74,7 @@ export interface SnapshotBlock {
|
|
|
71
74
|
* The structural table ops, named exactly as the agent proposal kinds and the
|
|
72
75
|
* MCP tool names — one vocabulary across the editor bridge, the agent, and MCP.
|
|
73
76
|
*/
|
|
74
|
-
export type TableOpKind = 'table_insert_row' | 'table_delete_row' | 'table_duplicate_row' | 'table_insert_column' | 'table_delete_column' | 'table_move_row' | 'table_move_column' | 'table_set_cell' | 'table_set_row_color' | 'table_set_column_color';
|
|
77
|
+
export type TableOpKind = 'table_insert_row' | 'table_delete_row' | 'table_duplicate_row' | 'table_insert_column' | 'table_delete_column' | 'table_move_row' | 'table_move_column' | 'table_set_cell' | 'table_set_row_color' | 'table_set_column_color' | 'table_set_column_width';
|
|
75
78
|
/** Every {@link TableOpKind}, for schema/description generation. */
|
|
76
79
|
export declare const TABLE_OP_KINDS: readonly TableOpKind[];
|
|
77
80
|
/**
|
|
@@ -89,10 +92,13 @@ export interface TableOpRequest {
|
|
|
89
92
|
colIndex?: number;
|
|
90
93
|
/** Move target, a sorted index counted with the moved row/column REMOVED. */
|
|
91
94
|
toIndex?: number;
|
|
92
|
-
/** New
|
|
93
|
-
text?:
|
|
95
|
+
/** New rich text (`table_set_cell`). */
|
|
96
|
+
text?: RichTextInput;
|
|
97
|
+
plain?: boolean;
|
|
94
98
|
/** Palette token, or null to clear (`table_set_row_color` / `..._column_color`). */
|
|
95
99
|
color?: string | null;
|
|
100
|
+
/** Integer pixel width, or null for auto (`table_set_column_width`). */
|
|
101
|
+
width?: number | null;
|
|
96
102
|
}
|
|
97
103
|
/** The dimensions an op is validated against (from the SORTED grid). */
|
|
98
104
|
export interface TableShape {
|
|
@@ -188,8 +194,10 @@ export interface TableOpAddress {
|
|
|
188
194
|
rowId?: string;
|
|
189
195
|
/** A column id (from `col:<id>` / a cell's `col` prop) — resolves `colIndex`. */
|
|
190
196
|
colId?: string;
|
|
191
|
-
text?:
|
|
197
|
+
text?: RichTextInput;
|
|
198
|
+
plain?: boolean;
|
|
192
199
|
color?: string | null;
|
|
200
|
+
width?: number | null;
|
|
193
201
|
}
|
|
194
202
|
/**
|
|
195
203
|
* Resolve id-based addressing to SORTED indices against a table view. An id that
|
package/dist/tableSnapshot.js
CHANGED
|
@@ -38,10 +38,13 @@
|
|
|
38
38
|
*/
|
|
39
39
|
import { shortId } from './database';
|
|
40
40
|
import { isOrderKey, keyBetween, keysBetween, ORDER_KEY_REBALANCE_LENGTH } from './orderKeys';
|
|
41
|
+
import { richTextRuns } from './richTextInput';
|
|
41
42
|
/** Prefix of the column-registry entries in a table block's props. */
|
|
42
43
|
export const TABLE_COL_PREFIX = 'col:';
|
|
43
44
|
/** Prefix of the per-column colour entries (`colbg:<colId>` → palette token). */
|
|
44
45
|
export const TABLE_COLBG_PREFIX = 'colbg:';
|
|
46
|
+
export const TABLE_COLW_PREFIX = 'colw:';
|
|
47
|
+
export const TABLE_COLUMN_MIN_WIDTH = 48;
|
|
45
48
|
/**
|
|
46
49
|
* The table order-contract PRIVATE keys (TBL-1): `row.props.ord`,
|
|
47
50
|
* `cell.props.col`, the `col:<id>` column registry, and the `colbg:<id>`
|
|
@@ -53,7 +56,7 @@ export const TABLE_COLBG_PREFIX = 'colbg:';
|
|
|
53
56
|
* none.
|
|
54
57
|
*/
|
|
55
58
|
export function tableOrderContractKey(props) {
|
|
56
|
-
return (Object.keys(props).find((k) => k === 'ord' || k === 'col' || k.startsWith(TABLE_COL_PREFIX) || k.startsWith(TABLE_COLBG_PREFIX)) ?? null);
|
|
59
|
+
return (Object.keys(props).find((k) => k === 'ord' || k === 'col' || k.startsWith(TABLE_COL_PREFIX) || k.startsWith(TABLE_COLBG_PREFIX) || k.startsWith(TABLE_COLW_PREFIX)) ?? null);
|
|
57
60
|
}
|
|
58
61
|
/** The shared refusal message for a {@link tableOrderContractKey} hit — the
|
|
59
62
|
* SAME wording on both write surfaces, naming the table tools that own the
|
|
@@ -71,6 +74,7 @@ export const TABLE_OP_KINDS = [
|
|
|
71
74
|
'table_set_cell',
|
|
72
75
|
'table_set_row_color',
|
|
73
76
|
'table_set_column_color',
|
|
77
|
+
'table_set_column_width',
|
|
74
78
|
];
|
|
75
79
|
const ordinal = (n) => `${n}`;
|
|
76
80
|
/**
|
|
@@ -116,6 +120,14 @@ export function tableOpError(shape, op) {
|
|
|
116
120
|
case 'table_delete_column':
|
|
117
121
|
case 'table_set_column_color':
|
|
118
122
|
return int(op.colIndex, 'colIndex') ?? inRange(op.colIndex, 'colIndex', cols - 1);
|
|
123
|
+
case 'table_set_column_width': {
|
|
124
|
+
const bad = int(op.colIndex, 'colIndex') ?? inRange(op.colIndex, 'colIndex', cols - 1);
|
|
125
|
+
if (bad)
|
|
126
|
+
return bad;
|
|
127
|
+
return op.width === null || (typeof op.width === 'number' && Number.isInteger(op.width) && op.width >= TABLE_COLUMN_MIN_WIDTH)
|
|
128
|
+
? null
|
|
129
|
+
: `width must be null or an integer at least ${TABLE_COLUMN_MIN_WIDTH}.`;
|
|
130
|
+
}
|
|
119
131
|
case 'table_move_row': {
|
|
120
132
|
const bad = int(op.rowIndex, 'rowIndex') ??
|
|
121
133
|
inRange(op.rowIndex, 'rowIndex', rows - 1) ??
|
|
@@ -135,7 +147,15 @@ export function tableOpError(shape, op) {
|
|
|
135
147
|
inRange(op.colIndex, 'colIndex', cols - 1);
|
|
136
148
|
if (bad)
|
|
137
149
|
return bad;
|
|
138
|
-
|
|
150
|
+
try {
|
|
151
|
+
if (op.text === undefined)
|
|
152
|
+
return 'text must be a string or {runs: Run[]}.';
|
|
153
|
+
richTextRuns(op.text, op.plain);
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
return error instanceof Error ? error.message : String(error);
|
|
158
|
+
}
|
|
139
159
|
}
|
|
140
160
|
default:
|
|
141
161
|
return `Unknown table op "${String(op.kind)}".`;
|
|
@@ -433,6 +453,8 @@ export function resolveTableOp(view, kind, address) {
|
|
|
433
453
|
op.text = address.text;
|
|
434
454
|
if (address.color !== undefined)
|
|
435
455
|
op.color = address.color;
|
|
456
|
+
if (address.width !== undefined)
|
|
457
|
+
op.width = address.width;
|
|
436
458
|
const positional = kind === 'table_insert_row' || kind === 'table_insert_column';
|
|
437
459
|
if (address.cellId !== undefined) {
|
|
438
460
|
let foundRow = -1;
|
|
@@ -579,6 +601,7 @@ export function applyTableOpToSnapshot(data, tableId, op) {
|
|
|
579
601
|
}
|
|
580
602
|
setProp(table, TABLE_COL_PREFIX + grid.colIds[at], undefined);
|
|
581
603
|
setProp(table, TABLE_COLBG_PREFIX + grid.colIds[at], undefined);
|
|
604
|
+
setProp(table, TABLE_COLW_PREFIX + grid.colIds[at], undefined);
|
|
582
605
|
grid.rows.forEach((row, r) => {
|
|
583
606
|
const cell = grid.cells[r][at];
|
|
584
607
|
if (!cell)
|
|
@@ -629,6 +652,7 @@ export function applyTableOpToSnapshot(data, tableId, op) {
|
|
|
629
652
|
// the same trade the snapshot `update_block` path makes (a JSON projection
|
|
630
653
|
// has no cursor or diff to preserve marks against; the live-editor path's
|
|
631
654
|
// `replaceText` splices minimally and does keep marks on unchanged ends).
|
|
655
|
+
const runs = richTextRuns(op.text ?? '', op.plain);
|
|
632
656
|
const cell = grid.cells[op.rowIndex ?? 0]?.[op.colIndex ?? 0];
|
|
633
657
|
// A merge gap has no cell node — materialize one bound to that column, so
|
|
634
658
|
// set_cell can fill a ragged/legacy table instead of failing on a hole.
|
|
@@ -636,10 +660,10 @@ export function applyTableOpToSnapshot(data, tableId, op) {
|
|
|
636
660
|
const row = grid.rows[op.rowIndex ?? 0];
|
|
637
661
|
const colId = grid.colIds[op.colIndex ?? 0];
|
|
638
662
|
if (row && colId)
|
|
639
|
-
kids(row).push({ ...newCell(colId), text:
|
|
663
|
+
kids(row).push({ ...newCell(colId), text: runs });
|
|
640
664
|
break;
|
|
641
665
|
}
|
|
642
|
-
cell.text =
|
|
666
|
+
cell.text = runs;
|
|
643
667
|
break;
|
|
644
668
|
}
|
|
645
669
|
case 'table_set_row_color': {
|
|
@@ -654,6 +678,12 @@ export function applyTableOpToSnapshot(data, tableId, op) {
|
|
|
654
678
|
setProp(table, TABLE_COLBG_PREFIX + colId, op.color ?? undefined);
|
|
655
679
|
break;
|
|
656
680
|
}
|
|
681
|
+
case 'table_set_column_width': {
|
|
682
|
+
const colId = grid.colIds[op.colIndex ?? 0];
|
|
683
|
+
if (colId)
|
|
684
|
+
setProp(table, TABLE_COLW_PREFIX + colId, op.width ?? undefined);
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
657
687
|
}
|
|
658
688
|
const bd = data.blockdoc;
|
|
659
689
|
return { data: { ...data, blockdoc: { ...bd, update: undefined, blocks } }, removedTable };
|