shelving 1.51.0 → 1.51.1

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/markup/render.js CHANGED
@@ -15,12 +15,12 @@ function renderString(content, options) {
15
15
  let matchedRule = undefined;
16
16
  let matchedResult = undefined;
17
17
  for (const rule of options.rules) {
18
- const { priority = 0, match, contexts } = rule;
18
+ const { priority = 0, match, regexp, contexts } = rule;
19
19
  // Only apply this rule if both:
20
20
  // 1. The priority is equal or higher to the current priority.
21
21
  // 2. The rule is allowed in the current context.
22
22
  if (priority >= matchedPriority && contexts.includes(options.context)) {
23
- const result = match(content, options);
23
+ const result = match ? match(content, options) : regexp ? content.match(regexp) : null;
24
24
  // If this matched and has an index (it might not if it's a `/g` global RegExp, which would be a mistake).
25
25
  if (result && typeof result.index === "number") {
26
26
  const index = result.index;
package/markup/rules.js CHANGED
@@ -3,8 +3,6 @@ import { formatUrl, toURL, getLineRegExp, MATCH_LINE, getBlockRegExp, MATCH_BLOC
3
3
  const BULLETS = "-*•+"; // Anything that can be a bullet (used for unordered lists and horizontal rules).
4
4
  // Regular expressions.
5
5
  const REPLACE_INDENT = /^ {1,2}/gm;
6
- // Regular expression makers.
7
- const getMatcher = regexp => content => content.match(regexp);
8
6
  /**
9
7
  * Headings are single line only (don't allow multiline).
10
8
  * - 1-6 hashes then 1+ spaces, then the title.
@@ -12,7 +10,7 @@ const getMatcher = regexp => content => content.match(regexp);
12
10
  * - Markdown's underline syntax is not supported (for simplification).
13
11
  */
14
12
  export const HEADING_RULE = {
15
- match: getMatcher(getLineRegExp(`(#{1,6}) +(${MATCH_LINE})`)),
13
+ regexp: getLineRegExp(`(#{1,6}) +(${MATCH_LINE})`),
16
14
  render: ([, prefix = "", children = ""]) => ({ type: `h${prefix.length}`, key: null, props: { children } }),
17
15
  contexts: ["block"],
18
16
  childContext: "inline",
@@ -25,7 +23,7 @@ export const HEADING_RULE = {
25
23
  * - Might have infinite number of spaces between the characters.
26
24
  */
27
25
  export const HORIZONTAL_RULE = {
28
- match: getMatcher(getLineRegExp(`([${BULLETS}])(?: *\\1){2,}`)),
26
+ regexp: getLineRegExp(`([${BULLETS}])(?: *\\1){2,}`),
29
27
  render: () => ({ type: "hr", key: null, props: {} }),
30
28
  contexts: ["block"],
31
29
  };
@@ -38,7 +36,7 @@ export const HORIZONTAL_RULE = {
38
36
  */
39
37
  const UNORDERED = `[${BULLETS}] +`; // Anything that can be a bullet (used for unordered lists and horizontal rules).
40
38
  export const UNORDERED_LIST_RULE = {
41
- match: getMatcher(getBlockRegExp(`${UNORDERED}(${MATCH_BLOCK})`)),
39
+ regexp: getBlockRegExp(`${UNORDERED}(${MATCH_BLOCK})`),
42
40
  render: ([, list = ""]) => {
43
41
  const children = list.split(SPLIT_UL_ITEMS).map(mapUnorderedItem);
44
42
  return { type: "ul", key: null, props: { children } };
@@ -58,7 +56,7 @@ const mapUnorderedItem = (item, key) => {
58
56
  */
59
57
  const ORDERED = "[0-9]+[.):] +"; // Number for a numbered list (e.g. `1.` or `2)` or `3:`)
60
58
  export const ORDERED_LIST_RULE = {
61
- match: getMatcher(getBlockRegExp(`(${ORDERED}${MATCH_BLOCK})`)),
59
+ regexp: getBlockRegExp(`(${ORDERED}${MATCH_BLOCK})`),
62
60
  render: ([, list = ""]) => {
63
61
  const children = list.split(SPLIT_OL_ITEMS).map(mapOrderedItem);
64
62
  return { type: "ol", key: null, props: { children } };
@@ -83,7 +81,7 @@ const mapOrderedItem = (item, key) => {
83
81
  * - Quote indent symbol can be followed by zero or more spaces.
84
82
  */
85
83
  export const BLOCKQUOTE_RULE = {
86
- match: getMatcher(getLineRegExp(`(>${MATCH_LINE}(?:\\n>${MATCH_LINE})*)`)),
84
+ regexp: getLineRegExp(`(>${MATCH_LINE}(?:\\n>${MATCH_LINE})*)`),
87
85
  render: ([, quote = ""]) => ({
88
86
  type: "blockquote",
89
87
  key: null,
@@ -102,7 +100,7 @@ const BLOCKQUOTE_LINES = /^>/gm;
102
100
  */
103
101
  export const FENCED_CODE_RULE = {
104
102
  // Matcher has its own end that only stops when it reaches a matching closing fence or the end of the string.
105
- match: getMatcher(getBlockRegExp(`(\`{3,}|~{3,}) *(${MATCH_LINE})\\n(${MATCH_BLOCK})`, `\\n\\1\\n+|\\n\\1$|$`)),
103
+ regexp: getBlockRegExp(`(\`{3,}|~{3,}) *(${MATCH_LINE})\\n(${MATCH_BLOCK})`, `\\n\\1\\n+|\\n\\1$|$`),
106
104
  render: ([, , file, children]) => ({
107
105
  type: "pre",
108
106
  key: null,
@@ -121,7 +119,7 @@ export const FENCED_CODE_RULE = {
121
119
  * - When ordering rules, paragraph should go after other "block" context elements (because it has a very generous capture).
122
120
  */
123
121
  export const PARAGRAPH_RULE = {
124
- match: getMatcher(getBlockRegExp(` *(${MATCH_BLOCK})`)),
122
+ regexp: getBlockRegExp(` *(${MATCH_BLOCK})`),
125
123
  render: ([, children]) => ({ type: `p`, key: null, props: { children } }),
126
124
  contexts: ["block"],
127
125
  childContext: "inline",
@@ -137,8 +135,9 @@ export const PARAGRAPH_RULE = {
137
135
  */
138
136
  export const LINK_MARKUP = {
139
137
  // Custom matcher to check the URL against the allowed schemes.
138
+ regexp: /\[([^\]]*?)\]\(([^)]*?)\)/,
140
139
  match: (content, { schemes, url: base }) => {
141
- const matches = content.match(MATCH_LINK);
140
+ const matches = content.match(LINK_MARKUP.regexp);
142
141
  if (matches && typeof matches.index === "number") {
143
142
  const [, title = "", href = ""] = matches;
144
143
  const url = toURL(href, base);
@@ -157,7 +156,6 @@ export const LINK_MARKUP = {
157
156
  contexts: ["inline", "list"],
158
157
  childContext: "link",
159
158
  };
160
- const MATCH_LINK = /\[([^\]]*?)\]\(([^)]*?)\)/;
161
159
  /**
162
160
  * Autolinked URL starts with `http:` or `https:` and matches an unlimited number of non-space characters.
163
161
  * - 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).
@@ -167,8 +165,9 @@ const MATCH_LINK = /\[([^\]]*?)\]\(([^)]*?)\)/;
167
165
  */
168
166
  export const AUTOLINK_RULE = {
169
167
  // Custom matcher to check the URL against the allowed schemes.
168
+ regexp: /([a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9]:\S+)(?: +(?:\(([^)]*?)\)|\[([^\]]*?)\]))?/,
170
169
  match: (content, { schemes, url: base }) => {
171
- const matches = content.match(MATCH_AUTOLINK);
170
+ const matches = content.match(AUTOLINK_RULE.regexp);
172
171
  if (matches && typeof matches.index === "number") {
173
172
  const [, href = "", title1 = "", title2 = ""] = matches;
174
173
  const url = toURL(href, base);
@@ -183,7 +182,6 @@ export const AUTOLINK_RULE = {
183
182
  contexts: ["inline", "list"],
184
183
  childContext: "link",
185
184
  };
186
- const MATCH_AUTOLINK = /([a-z][a-z0-9-]*[a-z0-9]:\S+)(?: +(?:\(([^)]*?)\)|\[([^\]]*?)\]))?/i;
187
185
  /**
188
186
  * Inline code.
189
187
  * - Text surrounded by one or more "`" backtick tilde characters.
@@ -192,7 +190,7 @@ const MATCH_AUTOLINK = /([a-z][a-z0-9-]*[a-z0-9]:\S+)(?: +(?:\(([^)]*?)\)|\[([^\
192
190
  * - Same as Markdown syntax.
193
191
  */
194
192
  export const CODE_RULE = {
195
- match: getMatcher(getWrapRegExp("`+", MATCH_BLOCK)),
193
+ regexp: getWrapRegExp("`+", MATCH_BLOCK),
196
194
  render: ([, , children]) => ({ type: "code", key: null, props: { children } }),
197
195
  contexts: ["inline", "list"],
198
196
  priority: 10, // Higher priority than other inlines so it matches first before e.g. `strong` or `em` (from CommonMark spec: "Code span backticks have higher precedence than any other inline constructs except HTML tags and autolinks.")
@@ -206,7 +204,7 @@ export const CODE_RULE = {
206
204
  * - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
207
205
  */
208
206
  export const STRONG_MARKUP = {
209
- match: getMatcher(getWrapRegExp("\\*+")),
207
+ regexp: getWrapRegExp("\\*+"),
210
208
  render: ([, , children]) => ({ type: "strong", key: null, props: { children } }),
211
209
  contexts: ["inline", "list", "link"],
212
210
  childContext: "inline",
@@ -220,7 +218,7 @@ export const STRONG_MARKUP = {
220
218
  * - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
221
219
  */
222
220
  export const EMPHASIS_RULE = {
223
- match: getMatcher(getWrapRegExp("_+")),
221
+ regexp: getWrapRegExp("_+"),
224
222
  render: ([, , children]) => ({ type: "em", key: null, props: { children } }),
225
223
  contexts: ["inline", "list", "link"],
226
224
  childContext: "inline",
@@ -234,7 +232,7 @@ export const EMPHASIS_RULE = {
234
232
  * - Markdown doesn't have this.
235
233
  */
236
234
  export const INSERT_RULE = {
237
- match: getMatcher(getWrapRegExp("\\+\\++")),
235
+ regexp: getWrapRegExp("\\+\\++"),
238
236
  render: ([, , children]) => ({ type: "ins", key: null, props: { children } }),
239
237
  contexts: ["inline", "list", "link"],
240
238
  childContext: "inline",
@@ -248,7 +246,7 @@ export const INSERT_RULE = {
248
246
  * - Markdown doesn't have this.
249
247
  */
250
248
  export const DELETE_RULE = {
251
- match: getMatcher(getWrapRegExp("--+|~~+")),
249
+ regexp: getWrapRegExp("--+|~~+"),
252
250
  render: ([, , children]) => ({ type: "del", key: null, props: { children } }),
253
251
  contexts: ["inline", "list", "link"],
254
252
  childContext: "inline",
@@ -262,7 +260,7 @@ export const DELETE_RULE = {
262
260
  * - This works better with textareas that wrap text (since manually breaking up long lines is no longer necessary).
263
261
  */
264
262
  export const LINEBREAK_RULE = {
265
- match: getMatcher(/\n/),
263
+ regexp: /\n/,
266
264
  render: () => ({ type: "br", key: null, props: {} }),
267
265
  contexts: ["inline", "list", "link"],
268
266
  childContext: "inline",
package/markup/types.d.ts CHANGED
@@ -18,8 +18,10 @@ export declare type MarkupElementProps = {
18
18
  export declare type MarkupNode = undefined | null | string | MarkupElement | MarkupNode[];
19
19
  /** A single markup parsing rule. */
20
20
  export declare type MarkupRule = {
21
- /** RegExp that matches this rule. */
22
- readonly match: MarkupRuleMatcher;
21
+ /** RegExp for matching this rule. */
22
+ readonly regexp: RegExp;
23
+ /** Custom matching function for this rule (overrides `regexp` if present. */
24
+ readonly match?: (content: string, options: MarkupOptions) => RegExpMatchArray | null | undefined | void;
23
25
  /**
24
26
  * Return a corresponding JSX element for the match.
25
27
  * @param ...matches The matches from `match` RegExp (without the `0` zeroeth "whole match").
@@ -27,7 +29,7 @@ export declare type MarkupRule = {
27
29
  * - The `key` property is not required (will be set automatically).
28
30
  * - e.g. `{ type: "a", props: { href: "/example.html", className: "strong", children: "Children *can* include _syntax_" } }`
29
31
  */
30
- readonly render: MarkupRuleRenderer;
32
+ readonly render: (matches: RegExpMatchArray, options: MarkupOptions) => MarkupElement;
31
33
  /** Apply the rule only when in certain contexts, e.g. `["block", "inline", "list"]` */
32
34
  readonly contexts: string[];
33
35
  /** Context any string children returned from `render()` should be rendered with. */
@@ -42,8 +44,6 @@ export declare type MarkupRule = {
42
44
  */
43
45
  readonly priority?: number;
44
46
  };
45
- export declare type MarkupRuleMatcher = (content: string, options: MarkupOptions) => RegExpMatchArray | null | undefined | void;
46
- export declare type MarkupRuleRenderer = (matches: RegExpMatchArray, options: MarkupOptions) => MarkupElement;
47
47
  /** A set of parse rules (as an object or array). */
48
48
  export declare type MarkupRules = Iterable<MarkupRule>;
49
49
  /** The current parsing options (represents the current state of the parsing). */
@@ -59,5 +59,3 @@ export declare type MarkupOptions = {
59
59
  /** Valid URL schemes/protocols for links (including trailing commas), defaults to `[`http:`, `https:`]` */
60
60
  readonly schemes: string[];
61
61
  };
62
- /** The create element function. */
63
- export declare type MarkupElementCreator = (type: string, props?: MarkupElementProps | null) => MarkupElement;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.51.0",
14
+ "version": "1.51.1",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",