shelving 1.69.0 → 1.71.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/api/Resource.js +2 -2
- package/error/ValidationError.js +2 -1
- package/feedback/Feedback.d.ts +4 -16
- package/feedback/Feedback.js +8 -31
- package/markup/index.d.ts +1 -1
- package/markup/index.js +1 -1
- package/markup/options.d.ts +16 -0
- package/markup/options.js +9 -0
- package/markup/render.d.ts +4 -4
- package/markup/render.js +95 -123
- package/markup/rules.d.ts +113 -33
- package/markup/rules.js +195 -130
- package/observe/Subject.d.ts +1 -1
- package/package.json +2 -2
- package/query/Filter.d.ts +1 -1
- package/query/Filter.js +3 -2
- package/react/useDocument.js +3 -4
- package/react/useQuery.js +3 -4
- package/schema/AllowSchema.js +4 -4
- package/schema/ArraySchema.js +2 -2
- package/schema/LinkSchema.js +2 -2
- package/schema/index.d.ts +0 -1
- package/schema/index.js +0 -1
- package/test/util.d.ts +3 -2
- package/update/DataUpdate.js +4 -6
- package/util/array.d.ts +1 -2
- package/util/array.js +7 -5
- package/util/clone.js +2 -2
- package/util/color.js +3 -2
- package/util/data.d.ts +13 -2
- package/util/data.js +19 -0
- package/util/date.d.ts +17 -16
- package/util/date.js +4 -3
- package/util/debug.d.ts +15 -1
- package/util/debug.js +62 -22
- package/util/equal.d.ts +2 -2
- package/util/equal.js +12 -7
- package/util/filter.d.ts +0 -4
- package/util/filter.js +0 -6
- package/util/function.d.ts +2 -0
- package/util/hydrate.js +8 -7
- package/util/index.d.ts +1 -1
- package/util/index.js +1 -1
- package/util/iterate.d.ts +1 -1
- package/util/jsx.d.ts +7 -10
- package/util/jsx.js +15 -13
- package/util/map.d.ts +12 -21
- package/util/map.js +13 -9
- package/util/match.js +4 -3
- package/util/number.d.ts +2 -2
- package/util/number.js +5 -1
- package/util/object.d.ts +12 -8
- package/util/object.js +13 -12
- package/util/regexp.d.ts +56 -0
- package/util/regexp.js +60 -0
- package/util/set.d.ts +14 -0
- package/util/set.js +17 -0
- package/util/sort.d.ts +1 -1
- package/util/string.d.ts +43 -34
- package/util/string.js +83 -77
- package/util/template.d.ts +9 -4
- package/util/template.js +14 -20
- package/util/timeout.js +3 -3
- package/util/transform.d.ts +10 -6
- package/util/transform.js +5 -1
- package/util/units.d.ts +8 -8
- package/util/url.d.ts +7 -5
- package/util/url.js +17 -14
- package/util/validate.js +6 -8
- package/markup/types.d.ts +0 -44
- package/markup/types.js +0 -1
- package/schema/MapSchema.d.ts +0 -19
- package/schema/MapSchema.js +0 -29
- package/util/search.d.ts +0 -71
- package/util/search.js +0 -97
package/markup/rules.js
CHANGED
|
@@ -1,31 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const MATCH_INDENT = /^ {1,2}/gm;
|
|
1
|
+
/* eslint-disable import/export */
|
|
2
|
+
import { getBlockRegExp, getLineRegExp, getNamedRegExp, getWrapRegExp, MATCH_BLOCK, MATCH_LINE } from "../util/regexp.js";
|
|
3
|
+
import { formatURL, getOptionalURL } from "../util/url.js";
|
|
4
|
+
/** React security symbol — see https://github.com/facebook/react/pull/4832 */
|
|
5
|
+
const $$typeof = Symbol.for("react.element");
|
|
7
6
|
/**
|
|
8
7
|
* Headings are single line only (don't allow multiline).
|
|
9
8
|
* - 1-6 hashes then 1+ spaces, then the title.
|
|
10
9
|
* - Same as Markdown syntax.
|
|
11
10
|
* - Markdown's underline syntax is not supported (for simplification).
|
|
12
11
|
*/
|
|
12
|
+
export const MATCH_HEADING = getLineRegExp(`(?<prefix>#{1,6}) +(?<heading>${MATCH_LINE.source})`);
|
|
13
13
|
export const HEADING_RULE = {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
match: input => {
|
|
15
|
+
const match = MATCH_HEADING.exec(input);
|
|
16
|
+
if (match) {
|
|
17
|
+
const { index, 0: first, groups } = match;
|
|
18
|
+
const { prefix, heading } = groups;
|
|
19
|
+
return { index, 0: first, groups: { level: prefix.length, heading } };
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
render: ({ level, heading }) => ({
|
|
23
|
+
type: `h${level}`,
|
|
24
|
+
key: null,
|
|
25
|
+
ref: null,
|
|
26
|
+
$$typeof,
|
|
27
|
+
props: { children: heading.trim() },
|
|
28
|
+
}),
|
|
16
29
|
contexts: ["block"],
|
|
17
|
-
|
|
30
|
+
subcontext: "inline",
|
|
18
31
|
};
|
|
19
32
|
/**
|
|
20
33
|
* Horizontal rules
|
|
21
|
-
* - Same as Markdown syntax but also allows `•` bullet character (in addition to `-` dash, `+` plus, `*` asterisk,
|
|
34
|
+
* - Same as Markdown syntax but also allows `•` bullet character (in addition to `-` dash, `+` plus, `*` asterisk, `_` underscore).
|
|
22
35
|
* - Character must be repeated three (or more) times.
|
|
23
36
|
* - Character must be the same every time (can't mix)
|
|
24
37
|
* - Might have infinite number of spaces between the characters.
|
|
25
38
|
*/
|
|
26
39
|
export const HORIZONTAL_RULE = {
|
|
27
|
-
|
|
28
|
-
render: () => ({
|
|
40
|
+
match: getLineRegExp(`([-*•+_=])(?: *\\1){2,}`),
|
|
41
|
+
render: () => ({
|
|
42
|
+
type: "hr",
|
|
43
|
+
key: null,
|
|
44
|
+
ref: null,
|
|
45
|
+
$$typeof,
|
|
46
|
+
props: {},
|
|
47
|
+
}),
|
|
29
48
|
contexts: ["block"],
|
|
30
49
|
};
|
|
31
50
|
/**
|
|
@@ -35,64 +54,81 @@ export const HORIZONTAL_RULE = {
|
|
|
35
54
|
* - Lists can be created with `•` bullet characters (in addition to `-` dash, `+` plus, and `*` asterisk).
|
|
36
55
|
* - Second-level list can be indented with 1-2 spaces.
|
|
37
56
|
*/
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
57
|
+
const UNORDERED_PREFIX = `[-*•+] +`;
|
|
58
|
+
const UNORDERED_SPLIT = new RegExp(`\n+${UNORDERED_PREFIX}`, "g");
|
|
59
|
+
const UNORDERED_INDENT = /^\t/gm;
|
|
60
|
+
export const UNORDERED_RULE = {
|
|
61
|
+
match: getBlockRegExp(`${UNORDERED_PREFIX}(?<list>${MATCH_BLOCK.source})`),
|
|
62
|
+
render: ({ list }) => ({
|
|
63
|
+
type: "ul",
|
|
64
|
+
key: null,
|
|
65
|
+
ref: null,
|
|
66
|
+
$$typeof,
|
|
67
|
+
props: { children: list.split(UNORDERED_SPLIT).map(_mapUnordered) },
|
|
68
|
+
}),
|
|
45
69
|
contexts: ["block", "list"],
|
|
46
|
-
|
|
47
|
-
};
|
|
48
|
-
const SPLIT_UL_ITEMS = new RegExp(`\\n+${UNORDERED}`, "g");
|
|
49
|
-
const _mapUnorderedItem = (item, key) => {
|
|
50
|
-
const children = item.replace(MATCH_INDENT, "");
|
|
51
|
-
return { type: "li", key, ref: null, props: { children } };
|
|
70
|
+
subcontext: "list",
|
|
52
71
|
};
|
|
72
|
+
const _mapUnordered = (item, key) => ({
|
|
73
|
+
type: "li",
|
|
74
|
+
key,
|
|
75
|
+
ref: null,
|
|
76
|
+
$$typeof,
|
|
77
|
+
props: { children: item.replace(UNORDERED_INDENT, "") },
|
|
78
|
+
});
|
|
53
79
|
/**
|
|
54
80
|
* Ordered list.
|
|
55
81
|
* - No leading spaces are allowed for the top-level list.
|
|
56
82
|
* - Second-level list can be indented with 1-3 spaces.
|
|
57
83
|
*/
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
84
|
+
const ORDERED_PREFIX = "[1-9][0-9]{0,8}[.):] +"; // Number for a numbered list, e.g. `1.` or `2)` or `3:`
|
|
85
|
+
const ORDERED_SPLIT = new RegExp(`\n+(?=${ORDERED_PREFIX})`, "g");
|
|
86
|
+
const ORDERED_INDENT = UNORDERED_INDENT;
|
|
87
|
+
export const ORDERED_RULE = {
|
|
88
|
+
match: getBlockRegExp(`(?<list>${ORDERED_PREFIX}${MATCH_BLOCK.source})`),
|
|
89
|
+
render: ({ list }) => ({
|
|
90
|
+
type: "ol",
|
|
91
|
+
key: null,
|
|
92
|
+
ref: null,
|
|
93
|
+
$$typeof,
|
|
94
|
+
props: { children: list.split(ORDERED_SPLIT).map(_mapOrdered) },
|
|
95
|
+
}),
|
|
65
96
|
contexts: ["block", "list"],
|
|
66
|
-
|
|
67
|
-
};
|
|
68
|
-
const SPLIT_OL_ITEMS = new RegExp(`\\n+(?=${ORDERED})`, "g");
|
|
69
|
-
const _mapOrderedItem = (item, key) => {
|
|
70
|
-
const firstSpace = item.indexOf(" ");
|
|
71
|
-
const value = parseInt(item.slice(0, firstSpace), 10);
|
|
72
|
-
const children = item
|
|
73
|
-
.slice(firstSpace + 1)
|
|
74
|
-
.trimStart()
|
|
75
|
-
.replace(MATCH_INDENT, "");
|
|
76
|
-
return { type: "li", key, ref: null, props: { value, children } };
|
|
97
|
+
subcontext: "list",
|
|
77
98
|
};
|
|
99
|
+
const _mapOrdered = (item, key) => ({
|
|
100
|
+
type: "li",
|
|
101
|
+
key,
|
|
102
|
+
ref: null,
|
|
103
|
+
$$typeof,
|
|
104
|
+
props: {
|
|
105
|
+
value: parseInt(item, 10),
|
|
106
|
+
children: item
|
|
107
|
+
.slice(item.indexOf(" ") + 1)
|
|
108
|
+
.trim()
|
|
109
|
+
.replace(ORDERED_INDENT, ""),
|
|
110
|
+
},
|
|
111
|
+
});
|
|
78
112
|
/**
|
|
79
113
|
* Blockquote block.
|
|
80
114
|
* - Same as Markdown's syntax.
|
|
81
115
|
* - Block continues until it finds a line that doesn't start with `>`
|
|
82
116
|
* - Quote indent symbol can be followed by zero or more spaces.
|
|
83
117
|
*/
|
|
118
|
+
const BLOCKQUOTE_PREFIX = "> *";
|
|
119
|
+
const BLOCKQUOTE_INDENT = new RegExp(`^${BLOCKQUOTE_PREFIX}`, "gm");
|
|
84
120
|
export const BLOCKQUOTE_RULE = {
|
|
85
|
-
|
|
86
|
-
render: (
|
|
121
|
+
match: getLineRegExp(`(?<quote>${BLOCKQUOTE_PREFIX}${MATCH_LINE.source}(?:\n${BLOCKQUOTE_PREFIX}${MATCH_LINE.source})*)`),
|
|
122
|
+
render: ({ quote }) => ({
|
|
87
123
|
type: "blockquote",
|
|
88
124
|
key: null,
|
|
89
125
|
ref: null,
|
|
90
|
-
|
|
126
|
+
$$typeof,
|
|
127
|
+
props: { children: quote.replace(BLOCKQUOTE_INDENT, "") },
|
|
91
128
|
}),
|
|
92
129
|
contexts: ["block", "list"],
|
|
93
|
-
|
|
130
|
+
subcontext: "block",
|
|
94
131
|
};
|
|
95
|
-
const BLOCKQUOTE_LINES = /^>/gm;
|
|
96
132
|
/**
|
|
97
133
|
* Fenced code blocks
|
|
98
134
|
* - Same as Markdown syntax.
|
|
@@ -102,95 +138,85 @@ const BLOCKQUOTE_LINES = /^>/gm;
|
|
|
102
138
|
*/
|
|
103
139
|
export const FENCED_CODE_RULE = {
|
|
104
140
|
// Matcher has its own end that only stops when it reaches a matching closing fence or the end of the string.
|
|
105
|
-
|
|
106
|
-
render: (
|
|
141
|
+
match: getBlockRegExp(`(\`{3,}|~{3,}) *(?<title>${MATCH_LINE.source})\n(?<code>${MATCH_BLOCK.source})`, `\n\\1\n+|\n\\1$|$`),
|
|
142
|
+
render: ({ title, code }) => ({
|
|
107
143
|
type: "pre",
|
|
108
144
|
key: null,
|
|
109
145
|
ref: null,
|
|
146
|
+
$$typeof,
|
|
110
147
|
props: {
|
|
111
148
|
children: {
|
|
112
149
|
type: "code",
|
|
113
150
|
key: null,
|
|
114
151
|
ref: null,
|
|
115
|
-
|
|
152
|
+
$$typeof,
|
|
153
|
+
props: { title: (title === null || title === void 0 ? void 0 : title.trim()) || undefined, children: code.trim() },
|
|
116
154
|
},
|
|
117
155
|
},
|
|
118
156
|
}),
|
|
119
157
|
contexts: ["block", "list"],
|
|
158
|
+
priority: 10, // Higher priority than other blocks so e.g. lists inside fenced code don't become lists.
|
|
120
159
|
};
|
|
121
160
|
/**
|
|
122
161
|
* Paragraph.
|
|
123
162
|
* - When ordering rules, paragraph should go after other "block" context elements (because it has a very generous capture).
|
|
124
163
|
*/
|
|
125
164
|
export const PARAGRAPH_RULE = {
|
|
126
|
-
|
|
127
|
-
render: (
|
|
165
|
+
match: getBlockRegExp(`(?<paragraph>${MATCH_BLOCK.source})`),
|
|
166
|
+
render: ({ paragraph }) => ({
|
|
167
|
+
type: `p`,
|
|
168
|
+
key: null,
|
|
169
|
+
ref: null,
|
|
170
|
+
$$typeof,
|
|
171
|
+
props: { children: paragraph.trim() },
|
|
172
|
+
}),
|
|
128
173
|
contexts: ["block"],
|
|
129
|
-
|
|
174
|
+
subcontext: "inline",
|
|
130
175
|
priority: -10, // Lower precedence than other blocks so it matches last and paragraphs can be broken by other blocks.
|
|
131
176
|
};
|
|
132
177
|
/**
|
|
133
|
-
*
|
|
134
|
-
* -
|
|
178
|
+
* Autolinked URL starts with `http:` or `https:` or `mailto:` (any scheme in `options.schemes`) and matches an unlimited number of non-space characters.
|
|
179
|
+
* - If followed by space and then text in `()` round or `[]` square brackets that will be used as the title, e.g. `http://google.com/maps (Google Maps)` or `http://google.com/maps [Google Maps]` (this syntax is from Todoist and maybe other things too).
|
|
135
180
|
* - If no title is specified a cleaned up version of the URL will be used, e.g. `google.com/maps`
|
|
136
|
-
* - Does not need space before/after the link.
|
|
137
181
|
* - If link is not valid (using `new URL(url)` then unparsed text will be returned.
|
|
138
|
-
* - For security only
|
|
182
|
+
* - For security only schemes that appear in `options.schemes` will match (defaults to `http:` and `https:`).
|
|
139
183
|
*/
|
|
140
|
-
export const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
match: (
|
|
144
|
-
|
|
145
|
-
if (matches) {
|
|
146
|
-
const [, title = "", href = ""] = matches;
|
|
147
|
-
const url = toURL(href, base);
|
|
148
|
-
if (url && url.protocol && schemes.includes(url.protocol)) {
|
|
149
|
-
matches[1] = title.trim();
|
|
150
|
-
matches[2] = url.href;
|
|
151
|
-
return matches;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
render: ([, title, href = ""], { rel }) => ({
|
|
184
|
+
export const URL_CHAR = "[-$_@.&!*,=;/#?:%a-zA-Z0-9]";
|
|
185
|
+
export const URL_MATCH = getNamedRegExp(`(?<href>[a-z]+:${URL_CHAR}+)(?: +(?:\\((?<title>[^)]*?)\\)))?`);
|
|
186
|
+
export const URL_RULE = {
|
|
187
|
+
match: (input, options) => _urlMatch(URL_MATCH.exec(input), options),
|
|
188
|
+
render: ({ href, title }, { rel }) => ({
|
|
156
189
|
type: "a",
|
|
157
190
|
key: null,
|
|
158
191
|
ref: null,
|
|
159
|
-
|
|
192
|
+
$$typeof,
|
|
193
|
+
props: { children: title, href, rel },
|
|
160
194
|
}),
|
|
161
195
|
contexts: ["inline", "list"],
|
|
162
|
-
|
|
196
|
+
subcontext: "link",
|
|
163
197
|
};
|
|
198
|
+
function _urlMatch(match, { schemes, url: base }) {
|
|
199
|
+
if (match) {
|
|
200
|
+
const { 0: first, index, groups } = match;
|
|
201
|
+
const { href, title } = groups;
|
|
202
|
+
const url = getOptionalURL(href, base);
|
|
203
|
+
if (url && schemes.includes(url.protocol)) {
|
|
204
|
+
return { 0: first, index, groups: { href: url.href, title: (title === null || title === void 0 ? void 0 : title.trim()) || formatURL(url) } };
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
164
208
|
/**
|
|
165
|
-
*
|
|
166
|
-
* -
|
|
209
|
+
* Markdown-style link.
|
|
210
|
+
* - Link in standard Markdown format, e.g. `[Google Maps](http://google.com/maps)`
|
|
167
211
|
* - If no title is specified a cleaned up version of the URL will be used, e.g. `google.com/maps`
|
|
212
|
+
* - Does not need space before/after the link.
|
|
168
213
|
* - If link is not valid (using `new URL(url)` then unparsed text will be returned.
|
|
169
|
-
* - For security only
|
|
214
|
+
* - For security only `http://` or `https://` links will work (if invalid the unparsed text will be returned).
|
|
170
215
|
*/
|
|
171
|
-
export const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
match: (
|
|
175
|
-
const matches = content.match(AUTOLINK_RULE.regexp);
|
|
176
|
-
if (matches && typeof matches.index === "number") {
|
|
177
|
-
const [, href = "", roundTitle = "", squareTitle = ""] = matches;
|
|
178
|
-
const url = toURL(href, base);
|
|
179
|
-
if (url && url.protocol && schemes.includes(url.protocol)) {
|
|
180
|
-
matches[1] = url.href;
|
|
181
|
-
matches[2] = (roundTitle || squareTitle).trim();
|
|
182
|
-
return matches;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
render: ([, href = "", title], { rel }) => ({
|
|
187
|
-
type: "a",
|
|
188
|
-
key: null,
|
|
189
|
-
ref: null,
|
|
190
|
-
props: { children: title || formatUrl(href), href, rel },
|
|
191
|
-
}),
|
|
192
|
-
contexts: ["inline", "list"],
|
|
193
|
-
childContext: "link",
|
|
216
|
+
export const LINK_MATCH = getNamedRegExp(/\[(?<title>[^\]]*?)\]\((?<href>[^)]*?)\)/);
|
|
217
|
+
export const LINK_RULE = {
|
|
218
|
+
...URL_RULE,
|
|
219
|
+
match: (input, options) => _urlMatch(LINK_MATCH.exec(input), options),
|
|
194
220
|
};
|
|
195
221
|
/**
|
|
196
222
|
* Inline code.
|
|
@@ -200,10 +226,16 @@ export const AUTOLINK_RULE = {
|
|
|
200
226
|
* - Same as Markdown syntax.
|
|
201
227
|
*/
|
|
202
228
|
export const CODE_RULE = {
|
|
203
|
-
|
|
204
|
-
render: (
|
|
229
|
+
match: getWrapRegExp("`+", MATCH_BLOCK.source),
|
|
230
|
+
render: ({ text }) => ({
|
|
231
|
+
type: "code",
|
|
232
|
+
key: null,
|
|
233
|
+
ref: null,
|
|
234
|
+
$$typeof,
|
|
235
|
+
props: { children: text },
|
|
236
|
+
}),
|
|
205
237
|
contexts: ["inline", "list"],
|
|
206
|
-
priority: 10, // Higher priority than
|
|
238
|
+
priority: 10, // Higher priority than e.g. `strong` or `em` (from CommonMark spec: "Code span backticks have higher precedence than any other inline constructs except HTML tags and autolinks.")
|
|
207
239
|
};
|
|
208
240
|
/**
|
|
209
241
|
* Inline strong.
|
|
@@ -214,10 +246,16 @@ export const CODE_RULE = {
|
|
|
214
246
|
* - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
|
|
215
247
|
*/
|
|
216
248
|
export const STRONG_RULE = {
|
|
217
|
-
|
|
218
|
-
render: (
|
|
249
|
+
match: getWrapRegExp("\\*+"),
|
|
250
|
+
render: ({ text }) => ({
|
|
251
|
+
type: "strong",
|
|
252
|
+
key: null,
|
|
253
|
+
ref: null,
|
|
254
|
+
$$typeof,
|
|
255
|
+
props: { children: text },
|
|
256
|
+
}),
|
|
219
257
|
contexts: ["inline", "list", "link"],
|
|
220
|
-
|
|
258
|
+
subcontext: "inline",
|
|
221
259
|
};
|
|
222
260
|
/**
|
|
223
261
|
* Inline emphasis.
|
|
@@ -228,24 +266,36 @@ export const STRONG_RULE = {
|
|
|
228
266
|
* - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
|
|
229
267
|
*/
|
|
230
268
|
export const EMPHASIS_RULE = {
|
|
231
|
-
|
|
232
|
-
render: (
|
|
269
|
+
match: getWrapRegExp("_+"),
|
|
270
|
+
render: ({ text }) => ({
|
|
271
|
+
type: "em",
|
|
272
|
+
key: null,
|
|
273
|
+
ref: null,
|
|
274
|
+
$$typeof,
|
|
275
|
+
props: { children: text },
|
|
276
|
+
}),
|
|
233
277
|
contexts: ["inline", "list", "link"],
|
|
234
|
-
|
|
278
|
+
subcontext: "inline",
|
|
235
279
|
};
|
|
236
280
|
/**
|
|
237
281
|
* Inserted text (`<ins>` tag),
|
|
238
282
|
* - Inline text wrapped in two or more `++` pluses.
|
|
239
|
-
* - Works inside words (e.g. `magi
|
|
283
|
+
* - Works inside words (e.g. `magi++karp++carp`).
|
|
240
284
|
* - Whitespace cannot be the first or last character of the element (e.g. `+ abc +` will not work).
|
|
241
285
|
* - Closing characters must exactly match opening characters.
|
|
242
286
|
* - Markdown doesn't have this.
|
|
243
287
|
*/
|
|
244
288
|
export const INSERT_RULE = {
|
|
245
|
-
|
|
246
|
-
render: (
|
|
289
|
+
match: getWrapRegExp("\\+\\++"),
|
|
290
|
+
render: ({ text }) => ({
|
|
291
|
+
type: "ins",
|
|
292
|
+
key: null,
|
|
293
|
+
ref: null,
|
|
294
|
+
$$typeof,
|
|
295
|
+
props: { children: text },
|
|
296
|
+
}),
|
|
247
297
|
contexts: ["inline", "list", "link"],
|
|
248
|
-
|
|
298
|
+
subcontext: "inline",
|
|
249
299
|
};
|
|
250
300
|
/**
|
|
251
301
|
* Deleted text (`<del>` tag),
|
|
@@ -256,10 +306,16 @@ export const INSERT_RULE = {
|
|
|
256
306
|
* - Markdown doesn't have this.
|
|
257
307
|
*/
|
|
258
308
|
export const DELETE_RULE = {
|
|
259
|
-
|
|
260
|
-
render: (
|
|
309
|
+
match: getWrapRegExp("--+|~~+"),
|
|
310
|
+
render: ({ text }) => ({
|
|
311
|
+
type: "del",
|
|
312
|
+
key: null,
|
|
313
|
+
ref: null,
|
|
314
|
+
$$typeof,
|
|
315
|
+
props: { children: text },
|
|
316
|
+
}),
|
|
261
317
|
contexts: ["inline", "list", "link"],
|
|
262
|
-
|
|
318
|
+
subcontext: "inline",
|
|
263
319
|
};
|
|
264
320
|
/**
|
|
265
321
|
* Hard linebreak (`<br />` tag).
|
|
@@ -270,10 +326,16 @@ export const DELETE_RULE = {
|
|
|
270
326
|
* - This works better with textareas that wrap text (since manually breaking up long lines is no longer necessary).
|
|
271
327
|
*/
|
|
272
328
|
export const LINEBREAK_RULE = {
|
|
273
|
-
|
|
274
|
-
render: () => ({
|
|
329
|
+
match: /\n/,
|
|
330
|
+
render: () => ({
|
|
331
|
+
type: "br",
|
|
332
|
+
key: null,
|
|
333
|
+
ref: null,
|
|
334
|
+
$$typeof,
|
|
335
|
+
props: {},
|
|
336
|
+
}),
|
|
275
337
|
contexts: ["inline", "list", "link"],
|
|
276
|
-
|
|
338
|
+
subcontext: "inline",
|
|
277
339
|
};
|
|
278
340
|
/**
|
|
279
341
|
* All markup rules.
|
|
@@ -287,13 +349,13 @@ export const LINEBREAK_RULE = {
|
|
|
287
349
|
export const MARKUP_RULES = [
|
|
288
350
|
HEADING_RULE,
|
|
289
351
|
HORIZONTAL_RULE,
|
|
290
|
-
|
|
291
|
-
|
|
352
|
+
UNORDERED_RULE,
|
|
353
|
+
ORDERED_RULE,
|
|
292
354
|
BLOCKQUOTE_RULE,
|
|
293
355
|
FENCED_CODE_RULE,
|
|
294
356
|
PARAGRAPH_RULE,
|
|
295
357
|
LINK_RULE,
|
|
296
|
-
|
|
358
|
+
URL_RULE,
|
|
297
359
|
CODE_RULE,
|
|
298
360
|
STRONG_RULE,
|
|
299
361
|
EMPHASIS_RULE,
|
|
@@ -305,34 +367,37 @@ export const MARKUP_RULES = [
|
|
|
305
367
|
export const MARKUP_RULES_BLOCK = [
|
|
306
368
|
HEADING_RULE,
|
|
307
369
|
HORIZONTAL_RULE,
|
|
308
|
-
|
|
309
|
-
|
|
370
|
+
UNORDERED_RULE,
|
|
371
|
+
ORDERED_RULE,
|
|
310
372
|
BLOCKQUOTE_RULE,
|
|
311
373
|
FENCED_CODE_RULE,
|
|
312
374
|
PARAGRAPH_RULE,
|
|
375
|
+
//
|
|
313
376
|
];
|
|
314
377
|
/** Subset of markup rules that work in an inline context. */
|
|
315
378
|
export const MARKUP_RULES_INLINE = [
|
|
316
379
|
LINK_RULE,
|
|
317
|
-
|
|
380
|
+
URL_RULE,
|
|
318
381
|
CODE_RULE,
|
|
319
382
|
STRONG_RULE,
|
|
320
383
|
EMPHASIS_RULE,
|
|
321
384
|
INSERT_RULE,
|
|
322
385
|
DELETE_RULE,
|
|
323
386
|
LINEBREAK_RULE,
|
|
387
|
+
//
|
|
324
388
|
];
|
|
325
389
|
/** Subset of markup rules that are relevant for collapsed shortform content. */
|
|
326
390
|
export const MARKUP_RULES_SHORTFORM = [
|
|
327
|
-
|
|
328
|
-
|
|
391
|
+
UNORDERED_RULE,
|
|
392
|
+
ORDERED_RULE,
|
|
329
393
|
PARAGRAPH_RULE,
|
|
330
394
|
LINK_RULE,
|
|
331
|
-
|
|
395
|
+
URL_RULE,
|
|
332
396
|
CODE_RULE,
|
|
333
397
|
STRONG_RULE,
|
|
334
398
|
EMPHASIS_RULE,
|
|
335
399
|
INSERT_RULE,
|
|
336
400
|
DELETE_RULE,
|
|
337
401
|
LINEBREAK_RULE,
|
|
402
|
+
//
|
|
338
403
|
];
|
package/observe/Subject.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export declare class Subject<T> implements Observable<T>, ConnectableObserver<T>
|
|
|
24
24
|
error(reason: Error | unknown): void;
|
|
25
25
|
complete(): void;
|
|
26
26
|
/** Close this subject (called by `error()` and `complete()`). */
|
|
27
|
-
|
|
27
|
+
protected _close(): void;
|
|
28
28
|
/** Connect this subject to a source. */
|
|
29
29
|
connect(source: Subscribable<T>): Unsubscribe;
|
|
30
30
|
/** Disconnect this subject from all sources. */
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"state-management",
|
|
12
12
|
"query-builder"
|
|
13
13
|
],
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.71.0",
|
|
15
15
|
"repository": "https://github.com/dhoulb/shelving",
|
|
16
16
|
"author": "Dave Houlbrooke <dave@shax.com>",
|
|
17
17
|
"license": "0BSD",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@google-cloud/firestore": "^5.0.2",
|
|
65
|
-
"@types/jest": "^
|
|
65
|
+
"@types/jest": "^28.1.6",
|
|
66
66
|
"@types/react": "^18.0.9",
|
|
67
67
|
"@types/react-dom": "^18.0.4",
|
|
68
68
|
"@typescript-eslint/eslint-plugin": "^5.23.0",
|
package/query/Filter.d.ts
CHANGED
package/query/Filter.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isArray } from "../util/array.js";
|
|
1
2
|
import { getProp } from "../util/data.js";
|
|
2
3
|
import { isArrayWith, isEqual, isEqualGreater, isEqualLess, isGreater, isInArray, isLess, notEqual, notInArray } from "../util/match.js";
|
|
3
4
|
import { filterItems } from "../util/filter.js";
|
|
@@ -31,7 +32,7 @@ export class Filter extends Rule {
|
|
|
31
32
|
/** Parse a set of FilterProps and return the corresponding array of `Filter` instances. */
|
|
32
33
|
static on(key, value) {
|
|
33
34
|
return key.startsWith("!")
|
|
34
|
-
? new Filter(key.slice(1), value
|
|
35
|
+
? new Filter(key.slice(1), isArray(value) ? "OUT" : "NOT", value)
|
|
35
36
|
: key.endsWith(">")
|
|
36
37
|
? new Filter(key.slice(0, -1), "GT", value)
|
|
37
38
|
: key.endsWith(">=")
|
|
@@ -42,7 +43,7 @@ export class Filter extends Rule {
|
|
|
42
43
|
? new Filter(key.slice(0, -2), "LTE", value)
|
|
43
44
|
: key.endsWith("[]")
|
|
44
45
|
? new Filter(key.slice(0, -2), "CONTAINS", value)
|
|
45
|
-
: new Filter(key, value
|
|
46
|
+
: new Filter(key, isArray(value) ? "IN" : "IS", value);
|
|
46
47
|
}
|
|
47
48
|
match(item) {
|
|
48
49
|
return MATCHERS[this.operator](getProp(item, this.key), this.value);
|
package/react/useDocument.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { setMapItem } from "../util/map.js";
|
|
2
2
|
import { getDocumentData } from "../db/Reference.js";
|
|
3
3
|
import { CacheProvider } from "../provider/CacheProvider.js";
|
|
4
4
|
import { getOptionalSourceProvider } from "../provider/ThroughProvider.js";
|
|
@@ -76,11 +76,10 @@ export class DocumentState extends State {
|
|
|
76
76
|
this.disconnect();
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
/** Reuse the previous `DocumentState` or create a new one. */
|
|
80
|
-
const _reduceDocumentState = (existing, ref) => existing || new DocumentState(ref);
|
|
81
79
|
export function useDocument(ref) {
|
|
82
80
|
const cache = useCache();
|
|
83
|
-
const
|
|
81
|
+
const key = ref === null || ref === void 0 ? void 0 : ref.toString();
|
|
82
|
+
const state = ref && key ? cache.get(key) || setMapItem(cache, key, new DocumentState(ref)) : undefined;
|
|
84
83
|
useSubscribe(state);
|
|
85
84
|
return state;
|
|
86
85
|
}
|
package/react/useQuery.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { setMapItem } from "../util/map.js";
|
|
2
2
|
import { getQueryFirstData, getQueryFirstValue } from "../db/Reference.js";
|
|
3
3
|
import { CacheProvider } from "../provider/CacheProvider.js";
|
|
4
4
|
import { getOptionalSourceProvider } from "../provider/ThroughProvider.js";
|
|
@@ -123,11 +123,10 @@ export class QueryState extends State {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
/** Reuse the previous `QueryState` or create a new one. */
|
|
127
|
-
const _reduceQueryState = (existing, ref) => existing || new QueryState(ref);
|
|
128
126
|
export function useQuery(ref) {
|
|
129
127
|
const cache = useCache();
|
|
130
|
-
const
|
|
128
|
+
const key = ref === null || ref === void 0 ? void 0 : ref.toString();
|
|
129
|
+
const state = ref && key ? cache.get(key) || setMapItem(cache, key, new QueryState(ref)) : undefined;
|
|
131
130
|
useSubscribe(state);
|
|
132
131
|
return state;
|
|
133
132
|
}
|
package/schema/AllowSchema.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { InvalidFeedback } from "../feedback/InvalidFeedback.js";
|
|
2
2
|
import { getString } from "../util/string.js";
|
|
3
|
-
import { isItem } from "../util/array.js";
|
|
3
|
+
import { isArray, isItem } from "../util/array.js";
|
|
4
4
|
import { getOptionalNumber } from "../util/number.js";
|
|
5
|
-
import {
|
|
5
|
+
import { isEntry } from "../util/object.js";
|
|
6
6
|
import { Schema } from "./Schema.js";
|
|
7
7
|
/** Validate a value against a specific set of allowed values. */
|
|
8
8
|
export function validateAllowed(value, allowed) {
|
|
9
|
-
if (allowed
|
|
9
|
+
if (isArray(allowed)) {
|
|
10
10
|
if (isItem(allowed, value))
|
|
11
11
|
return value;
|
|
12
12
|
}
|
|
13
13
|
else {
|
|
14
|
-
if (
|
|
14
|
+
if (isEntry(allowed, value))
|
|
15
15
|
return value;
|
|
16
16
|
}
|
|
17
17
|
throw new InvalidFeedback("Unknown value", { value });
|
package/schema/ArraySchema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InvalidFeedback } from "../feedback/InvalidFeedback.js";
|
|
2
|
-
import { uniqueArray } from "../util/array.js";
|
|
2
|
+
import { isArray, uniqueArray } from "../util/array.js";
|
|
3
3
|
import { validateArray } from "../util/validate.js";
|
|
4
4
|
import { Schema } from "./Schema.js";
|
|
5
5
|
/**
|
|
@@ -39,7 +39,7 @@ export class ArraySchema extends Schema {
|
|
|
39
39
|
this.max = max;
|
|
40
40
|
}
|
|
41
41
|
validate(unsafeValue = this.value) {
|
|
42
|
-
if (!(unsafeValue
|
|
42
|
+
if (!isArray(unsafeValue))
|
|
43
43
|
throw new InvalidFeedback("Must be array", { value: unsafeValue });
|
|
44
44
|
const safeArray = validateArray(unsafeValue, this.items);
|
|
45
45
|
const dedupedArray = this.unique ? uniqueArray(safeArray) : safeArray;
|
package/schema/LinkSchema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InvalidFeedback } from "../feedback/InvalidFeedback.js";
|
|
2
|
-
import {
|
|
2
|
+
import { getOptionalURL } from "../util/url.js";
|
|
3
3
|
import { OPTIONAL } from "./OptionalSchema.js";
|
|
4
4
|
import { StringSchema } from "./StringSchema.js";
|
|
5
5
|
/**
|
|
@@ -22,7 +22,7 @@ export class LinkSchema extends StringSchema {
|
|
|
22
22
|
// Override to clean the URL using the builtin `URL` class and check the schemes and hosts against the whitelists.
|
|
23
23
|
validate(unsafeValue) {
|
|
24
24
|
const string = super.validate(unsafeValue);
|
|
25
|
-
const url =
|
|
25
|
+
const url = getOptionalURL(super.sanitize(string));
|
|
26
26
|
if (!url)
|
|
27
27
|
throw new InvalidFeedback(string ? "Invalid format" : "Required", { value: string });
|
|
28
28
|
if (!this.schemes.includes(url.protocol))
|