shelving 1.110.0 → 1.110.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
@@ -66,8 +66,7 @@ function _renderNode(node, options, context) {
66
66
  * Render a JSX element in a given context.
67
67
  */
68
68
  function _renderElement(element, options, context) {
69
- if (element.props.children)
70
- element.props.children = _renderNode(element.props.children, options, context);
69
+ element.props.children = _renderNode(element.props.children, options, context);
71
70
  return element;
72
71
  }
73
72
  /**
@@ -75,9 +74,8 @@ function _renderElement(element, options, context) {
75
74
  *
76
75
  * @param offset Keeps track of where we are within the wider string we're parsing when we're several calls deep.
77
76
  */
78
- function* _parseString(input, options, context, offset = 0) {
79
- let matchedRule = undefined;
80
- let matchedResult = undefined;
77
+ function* _parseString(input, options, outerContext, offset = 0) {
78
+ let element = undefined;
81
79
  let highPriority = Number.MIN_SAFE_INTEGER;
82
80
  let lowIndex = Number.MIN_SAFE_INTEGER;
83
81
  // Loop through all rules in the list and see if any match.
@@ -85,15 +83,14 @@ function* _parseString(input, options, context, offset = 0) {
85
83
  // Only apply this rule if both:
86
84
  // 1. The priority is equal or higher to the current priority.
87
85
  // 2. The rule is allowed in the current context.
88
- const { priority } = rule;
89
- if (rule.priority >= highPriority && rule.contexts.includes(context)) {
90
- const result = rule.match(input, options);
91
- if (result) {
86
+ const { priority = 0, contexts } = rule;
87
+ if (priority >= highPriority && contexts.includes(outerContext)) {
88
+ const match = rule.match(input, options);
89
+ if (match) {
92
90
  // Use the match if it has length and is earlier in the string or is higher priority.
93
- const { 0: { length } = "", index } = result;
94
- if (length && (index < lowIndex || rule.priority > highPriority)) {
95
- matchedRule = rule;
96
- matchedResult = result;
91
+ const { index, length } = match;
92
+ if (length && (index < lowIndex || priority > highPriority)) {
93
+ element = match;
97
94
  highPriority = priority;
98
95
  lowIndex = index;
99
96
  }
@@ -101,24 +98,22 @@ function* _parseString(input, options, context, offset = 0) {
101
98
  }
102
99
  }
103
100
  // Did at least one rule match?
104
- if (matchedRule && matchedResult) {
101
+ if (element) {
105
102
  // If index is more than zero, then the string before the match may match another rule at lower priority.
106
103
  const prefix = input.slice(0, lowIndex);
107
104
  if (prefix.length)
108
- yield* _parseString(prefix, options, context, offset);
105
+ yield* _parseString(prefix, options, outerContext, offset);
109
106
  // Call the rule's `render()` function to generate the node.
110
107
  // React gets annoyed if we don't set a `key:` property on lists of elements.
111
108
  // We use the string offset as the `.key` property in the element because it's cheap to calculate and guaranteed to be unique within the string.
112
109
  // Trying to generate an incrementing number would require tracking the number and passing it back and forth through `_parseString()`
113
- const { 0: { length } = "", groups, index } = matchedResult;
114
- const element = matchedRule.render(groups, options);
110
+ const { index, length, context } = element;
115
111
  element.key = offset + index;
116
- const { subcontext } = matchedRule;
117
- yield subcontext ? _renderElement(element, options, subcontext) : element;
112
+ yield context ? _renderElement(element, options, context) : element;
118
113
  // Decrement the content.
119
114
  const suffix = input.slice(index + length);
120
115
  if (suffix.length)
121
- yield* _parseString(suffix, options, context, offset + index + length);
116
+ yield* _parseString(suffix, options, outerContext, offset + index + length);
122
117
  }
123
118
  else {
124
119
  // If nothing matched return the entire string..
package/markup/rule.d.ts CHANGED
@@ -1,74 +1,48 @@
1
1
  import type { MarkupOptions } from "./options.js";
2
2
  import type { ImmutableArray } from "../util/array.js";
3
- import type { Data } from "../util/data.js";
4
3
  import type { JSXElement } from "../util/jsx.js";
5
- import type { NamedRegExp, NamedRegExpArray, NamedRegExpData } from "../util/regexp.js";
6
- export type MarkupRuleMatch<T extends Data = Data> = {
7
- 0: string;
4
+ import type { NamedRegExp, NamedRegExpData, TypedRegExp, TypedRegExpExecArray } from "../util/regexp.js";
5
+ export type MarkupElement = {
6
+ /** String index where this element was matched in the input string. */
8
7
  index: number;
9
- groups?: T;
10
- };
11
- export declare abstract class MarkupRule {
8
+ /** String length where this element was matched in the input string. */
9
+ length: number;
10
+ /** Context for this element's children in the input string, e.g. `"inline"` */
11
+ context?: string;
12
+ } & JSXElement;
13
+ export interface MarkupRule {
12
14
  /**
13
15
  * Contexts this rule should be applied in,
14
16
  *
15
17
  * @example `["block", "inline", "list"]`
16
18
  */
17
19
  readonly contexts: ImmutableArray<string>;
18
- /**
19
- * Context that children should be rendered with.
20
- *
21
- * @example `"inline"` // Children of the element rendered by this rule will be parsed against markup rules applied in the "inline" context.
22
- */
23
- readonly subcontext: string | null;
24
20
  /**
25
21
  * Priority for this rule (defaults to zero).
26
22
  *
27
23
  * @example e.g. `<p>` rule is lower priority than other blocks so it matches last and paragraphs can be interrupted by e.g. `<ul>` and `<blockquote>`.
28
24
  * @example e.g. `<code>` rule is higher priority than other inlines so e.g. `<strong>` or `<em>` don't match inside a code block.
29
25
  */
30
- readonly priority: number;
31
- constructor(contexts: ImmutableArray<string>, //
32
- subcontext?: string | null, priority?: number);
33
- /** Match an input string against this */
34
- abstract match(input: string, options: MarkupOptions): MarkupRuleMatch | null;
35
- /** Render the JSX element for this rule using the props matched by `.match` */
36
- abstract render(props: Data | undefined, options: MarkupOptions): JSXElement;
26
+ readonly priority?: number | undefined;
27
+ /** Match an input string against this and return an element if there was a match. */
28
+ match(input: string, options: MarkupOptions): MarkupElement | undefined;
37
29
  }
38
- export declare class RegExpMarkupRule extends MarkupRule {
39
- readonly regexp: RegExp;
40
- readonly render: (props: Data, options: MarkupOptions) => JSXElement;
41
- constructor(regexp: RegExp, //
42
- render: (props: Data, options: MarkupOptions) => JSXElement, contexts: ImmutableArray<string>, subcontext?: string | null, priority?: number);
43
- match(input: string): MarkupRuleMatch | null;
44
- }
45
- export declare class NamedRegExpMarkupRule<T extends NamedRegExpData> extends MarkupRule {
46
- readonly regexp: NamedRegExp<T>;
47
- readonly render: (props: T, options: MarkupOptions) => JSXElement;
48
- constructor(regexp: NamedRegExp<T>, //
49
- render: (props: T, options: MarkupOptions) => JSXElement, contexts: ImmutableArray<string>, subcontext?: string | null, priority?: number);
50
- match(input: string): NamedRegExpArray<T> | null;
51
- }
52
- export declare class LinkRegExpMarkupRule extends MarkupRule {
53
- readonly regexp: NamedRegExp<{
30
+ export declare function getMarkupRule<T extends string = string>(regexp: TypedRegExp<T>, //
31
+ render: (props: TypedRegExpExecArray<T>, options: MarkupOptions) => JSXElement, contexts: ImmutableArray<string>, priority?: number): MarkupRule & {
32
+ regexp: TypedRegExp<T>;
33
+ };
34
+ export declare function getNamedMarkupRule<T extends NamedRegExpData>(regexp: NamedRegExp<T>, //
35
+ render: (data: T, options: MarkupOptions) => JSXElement, contexts: ImmutableArray<string>, priority?: number): MarkupRule & {
36
+ regexp: NamedRegExp<T>;
37
+ };
38
+ export declare function getLinkMarkupRule(regexp: NamedRegExp<{
39
+ title?: string;
40
+ href: string;
41
+ }>, //
42
+ render: (title: string, href: string, options: MarkupOptions) => JSXElement, contexts: ImmutableArray<string>, priority?: number): MarkupRule & {
43
+ regexp: NamedRegExp<{
54
44
  title?: string;
55
45
  href: string;
56
46
  }>;
57
- readonly render: (props: {
58
- title: string;
59
- href: string;
60
- }, options: MarkupOptions) => JSXElement;
61
- constructor(regexp: NamedRegExp<{
62
- title?: string;
63
- href: string;
64
- }>, //
65
- render: (props: {
66
- title: string;
67
- href: string;
68
- }, options: MarkupOptions) => JSXElement, contexts: ImmutableArray<string>, subcontext?: string | null, priority?: number);
69
- match(input: string, { schemes, url: base }: MarkupOptions): MarkupRuleMatch<{
70
- title: string;
71
- href: string;
72
- }> | null;
73
- }
47
+ };
74
48
  export type MarkupRules = MarkupRule[];
package/markup/rule.js CHANGED
@@ -1,79 +1,49 @@
1
1
  import { formatURL, getOptionalURL } from "../util/url.js";
2
- export class MarkupRule {
3
- /**
4
- * Contexts this rule should be applied in,
5
- *
6
- * @example `["block", "inline", "list"]`
7
- */
8
- contexts;
9
- /**
10
- * Context that children should be rendered with.
11
- *
12
- * @example `"inline"` // Children of the element rendered by this rule will be parsed against markup rules applied in the "inline" context.
13
- */
14
- subcontext;
15
- /**
16
- * Priority for this rule (defaults to zero).
17
- *
18
- * @example e.g. `<p>` rule is lower priority than other blocks so it matches last and paragraphs can be interrupted by e.g. `<ul>` and `<blockquote>`.
19
- * @example e.g. `<code>` rule is higher priority than other inlines so e.g. `<strong>` or `<em>` don't match inside a code block.
20
- */
21
- priority;
22
- constructor(contexts, //
23
- subcontext = null, priority = 0) {
24
- this.contexts = contexts;
25
- this.subcontext = subcontext;
26
- this.priority = priority;
27
- }
28
- }
29
- export class RegExpMarkupRule extends MarkupRule {
30
- regexp;
31
- render;
32
- constructor(regexp, //
33
- render, contexts, subcontext, priority) {
34
- super(contexts, subcontext, priority);
35
- this.regexp = regexp;
36
- this.render = render;
37
- }
38
- match(input) {
39
- return this.regexp.exec(input);
40
- }
2
+ export function getMarkupRule(regexp, //
3
+ render, contexts, priority) {
4
+ return {
5
+ regexp,
6
+ match(input, options) {
7
+ const match = regexp.exec(input);
8
+ if (match) {
9
+ const { index, 0: { length }, } = match;
10
+ return { index, length, ...render(match, options) };
11
+ }
12
+ },
13
+ contexts,
14
+ priority,
15
+ };
41
16
  }
42
- export class NamedRegExpMarkupRule extends MarkupRule {
43
- regexp;
44
- render;
45
- constructor(regexp, //
46
- render, contexts, subcontext, priority) {
47
- super(contexts, subcontext, priority);
48
- this.regexp = regexp;
49
- this.render = render;
50
- }
51
- match(input) {
52
- return this.regexp.exec(input);
53
- }
17
+ export function getNamedMarkupRule(regexp, //
18
+ render, contexts, priority) {
19
+ return {
20
+ regexp,
21
+ match(input, options) {
22
+ const match = regexp.exec(input);
23
+ if (match) {
24
+ const { index, 0: { length }, groups, } = match;
25
+ return { index, length, ...render(groups, options) };
26
+ }
27
+ },
28
+ contexts,
29
+ priority,
30
+ };
54
31
  }
55
- export class LinkRegExpMarkupRule extends MarkupRule {
56
- regexp;
57
- render;
58
- constructor(regexp, //
59
- render, contexts, subcontext, priority) {
60
- super(contexts, subcontext, priority);
61
- this.regexp = regexp;
62
- this.render = render;
63
- }
64
- // Validates that the link is a valid URL (using `getOptionalURL()` to resolve relative links relative to `options.url`).
65
- // Validates that the link's URL scheme is in the `options.schemes` whitelist (defaults to `http` and `https`).
66
- // Generates a default title for the link using `formatURL()` (e.g. `shax.com/my/dir`).
67
- match(input, { schemes, url: base }) {
68
- const match = this.regexp.exec(input);
69
- if (match) {
70
- const { 0: first, index, groups } = match;
71
- const { href, title } = groups;
72
- const url = getOptionalURL(href, base);
73
- if (url && schemes.includes(url.protocol)) {
74
- return { 0: first, index, groups: { href: url.href, title: title?.trim() || formatURL(url) } };
32
+ export function getLinkMarkupRule(regexp, //
33
+ render, contexts, priority) {
34
+ return {
35
+ regexp,
36
+ match(input, options) {
37
+ const match = this.regexp.exec(input);
38
+ if (match) {
39
+ const { schemes, url: base } = options;
40
+ const { 0: { length }, index, groups: { href, title }, } = match;
41
+ const url = getOptionalURL(href, base);
42
+ if (url && schemes.includes(url.protocol))
43
+ return { index, length, ...render(title?.trim() || formatURL(url), url.href, options) };
75
44
  }
76
- }
77
- return null;
78
- }
45
+ },
46
+ contexts,
47
+ priority,
48
+ };
79
49
  }
package/markup/rules.d.ts CHANGED
@@ -1,17 +1,18 @@
1
1
  import type { MarkupOptions } from "./options.js";
2
2
  import type { MarkupRules } from "./rule.js";
3
- import type { JSXElement } from "../util/jsx.js";
4
- import { LinkRegExpMarkupRule, NamedRegExpMarkupRule, RegExpMarkupRule } from "./rule.js";
3
+ import type { NamedRegExp } from "../util/regexp.js";
5
4
  /**
6
5
  * Headings are single line only (don't allow multiline).
7
6
  * - 1-6 hashes then 1+ spaces, then the title.
8
7
  * - Same as Markdown syntax.
9
8
  * - Markdown's underline syntax is not supported (for simplification).
10
9
  */
11
- export declare const HEADING_RULE: NamedRegExpMarkupRule<{
12
- prefix: string;
13
- heading: string;
14
- }>;
10
+ export declare const HEADING_RULE: import("./rule.js").MarkupRule & {
11
+ regexp: NamedRegExp<{
12
+ prefix: string;
13
+ heading: string;
14
+ }>;
15
+ };
15
16
  /**
16
17
  * Separator (horizontal rule / thematic break).
17
18
  * - Same as Markdown syntax but also allows `•` bullet character (in addition to `-` dash, `+` plus, `*` asterisk, `_` underscore).
@@ -19,16 +20,24 @@ export declare const HEADING_RULE: NamedRegExpMarkupRule<{
19
20
  * - Character must be the same every time (can't mix)
20
21
  * - Might have infinite number of spaces between the characters.
21
22
  */
22
- export declare const SEPARATOR_RULE: RegExpMarkupRule;
23
- export declare const UNORDERED_RULE: NamedRegExpMarkupRule<{
24
- list: string;
25
- }>;
26
- export declare const ORDERED_RULE: NamedRegExpMarkupRule<{
27
- list: string;
28
- }>;
29
- export declare const BLOCKQUOTE_RULE: NamedRegExpMarkupRule<{
30
- quote: string;
31
- }>;
23
+ export declare const SEPARATOR_RULE: import("./rule.js").MarkupRule & {
24
+ regexp: import("../util/regexp.js").TypedRegExp<string>;
25
+ };
26
+ export declare const UNORDERED_RULE: import("./rule.js").MarkupRule & {
27
+ regexp: NamedRegExp<{
28
+ list: string;
29
+ }>;
30
+ };
31
+ export declare const ORDERED_RULE: import("./rule.js").MarkupRule & {
32
+ regexp: NamedRegExp<{
33
+ list: string;
34
+ }>;
35
+ };
36
+ export declare const BLOCKQUOTE_RULE: import("./rule.js").MarkupRule & {
37
+ regexp: NamedRegExp<{
38
+ quote: string;
39
+ }>;
40
+ };
32
41
  /**
33
42
  * Fenced code blocks
34
43
  * - Same as Markdown syntax.
@@ -36,23 +45,35 @@ export declare const BLOCKQUOTE_RULE: NamedRegExpMarkupRule<{
36
45
  * - If there's no closing fence the code block will run to the end of the current string.
37
46
  * - Markdown-style four-space indent syntax is not supported (only fenced code, since it's easier to use).
38
47
  */
39
- export declare const FENCED_CODE_RULE: NamedRegExpMarkupRule<{
40
- wrap: string;
41
- title?: string;
42
- code: string;
43
- }>;
48
+ export declare const FENCED_CODE_RULE: import("./rule.js").MarkupRule & {
49
+ regexp: NamedRegExp<{
50
+ wrap: string;
51
+ title?: string;
52
+ code: string;
53
+ }>;
54
+ };
44
55
  /**
45
56
  * Paragraph.
46
57
  * - When ordering rules, paragraph should go after other "block" context elements (because it has a very generous capture).
47
58
  */
48
- export declare const PARAGRAPH_RULE: NamedRegExpMarkupRule<{
49
- paragraph: string;
50
- }>;
59
+ export declare const PARAGRAPH_RULE: import("./rule.js").MarkupRule & {
60
+ regexp: NamedRegExp<{
61
+ paragraph: string;
62
+ }>;
63
+ };
51
64
  /** Render function for URL and LINK rules. */
52
- export declare function renderLinkRule({ href, title }: {
53
- title: string;
54
- href: string;
55
- }, { rel }: MarkupOptions): JSXElement;
65
+ export declare function renderLinkRule(title: string, href: string, { rel }: MarkupOptions): {
66
+ type: string;
67
+ key: null;
68
+ ref: null;
69
+ $$typeof: symbol;
70
+ props: {
71
+ children: string;
72
+ href: string;
73
+ rel: string | undefined;
74
+ };
75
+ context: string;
76
+ };
56
77
  /**
57
78
  * Autolinked URL starts with `http:` or `https:` or `mailto:` (any scheme in `options.schemes`) and matches an unlimited number of non-space characters.
58
79
  * - 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).
@@ -60,7 +81,12 @@ export declare function renderLinkRule({ href, title }: {
60
81
  * - If link is not valid (using `new URL(url)` then unparsed text will be returned.
61
82
  * - For security only schemes that appear in `options.schemes` will match (defaults to `http:` and `https:`).
62
83
  */
63
- export declare const URL_RULE: LinkRegExpMarkupRule;
84
+ export declare const URL_RULE: import("./rule.js").MarkupRule & {
85
+ regexp: NamedRegExp<{
86
+ title?: string;
87
+ href: string;
88
+ }>;
89
+ };
64
90
  /**
65
91
  * Markdown-style link.
66
92
  * - Link in standard Markdown format, e.g. `[Google Maps](http://google.com/maps)`
@@ -69,7 +95,12 @@ export declare const URL_RULE: LinkRegExpMarkupRule;
69
95
  * - If link is not valid (using `new URL(url)` then unparsed text will be returned.
70
96
  * - For security only `http://` or `https://` links will work (if invalid the unparsed text will be returned).
71
97
  */
72
- export declare const LINK_RULE: LinkRegExpMarkupRule;
98
+ export declare const LINK_RULE: import("./rule.js").MarkupRule & {
99
+ regexp: NamedRegExp<{
100
+ title?: string;
101
+ href: string;
102
+ }>;
103
+ };
73
104
  /**
74
105
  * Inline code.
75
106
  * - Text surrounded by one or more "`" backtick tilde characters.
@@ -77,9 +108,11 @@ export declare const LINK_RULE: LinkRegExpMarkupRule;
77
108
  * - Closing characters must exactly match opening characters.
78
109
  * - Same as Markdown syntax.
79
110
  */
80
- export declare const CODE_RULE: NamedRegExpMarkupRule<{
81
- code: string;
82
- }>;
111
+ export declare const CODE_RULE: import("./rule.js").MarkupRule & {
112
+ regexp: NamedRegExp<{
113
+ code: string;
114
+ }>;
115
+ };
83
116
  /**
84
117
  * Inline strong, emphasis, insert, delete, highlight.
85
118
  * - Inline strong text wrapped in one or more `*` asterisks.
@@ -102,11 +135,13 @@ declare const INLINE_CHARS: {
102
135
  "=": string;
103
136
  ":": string;
104
137
  };
105
- export declare const INLINE_RULE: NamedRegExpMarkupRule<{
106
- char: keyof typeof INLINE_CHARS;
107
- wrap: string;
108
- text: string;
109
- }>;
138
+ export declare const INLINE_RULE: import("./rule.js").MarkupRule & {
139
+ regexp: NamedRegExp<{
140
+ char: keyof typeof INLINE_CHARS;
141
+ wrap: string;
142
+ text: string;
143
+ }>;
144
+ };
110
145
  /**
111
146
  * Hard linebreak (`<br />` tag).
112
147
  * - Any line break in a paragraph will become a hard `<br />` tag.
@@ -115,7 +150,9 @@ export declare const INLINE_RULE: NamedRegExpMarkupRule<{
115
150
  * - This is more intuitive (a linebreak becomes a linebreak is isn't silently ignored).
116
151
  * - This works better with textareas that wrap text (since manually breaking up long lines is no longer necessary).
117
152
  */
118
- export declare const LINEBREAK_RULE: RegExpMarkupRule;
153
+ export declare const LINEBREAK_RULE: import("./rule.js").MarkupRule & {
154
+ regexp: import("../util/regexp.js").TypedRegExp<string>;
155
+ };
119
156
  /**
120
157
  * All markup rules.
121
158
  * - Syntax parsed by `renderMarkup()` is defined entirely by the list of rules (i.e. not by code).
package/markup/rules.js CHANGED
@@ -1,7 +1,6 @@
1
- /* eslint-disable import/export */
2
1
  import { getRegExp } from "../util/regexp.js";
3
2
  import { BLOCK_REGEXP, LINE_REGEXP, WordRegExp, getBlockRegExp, getLineRegExp } from "./regexp.js";
4
- import { LinkRegExpMarkupRule, NamedRegExpMarkupRule, RegExpMarkupRule } from "./rule.js";
3
+ import { getLinkMarkupRule, getMarkupRule, getNamedMarkupRule } from "./rule.js";
5
4
  /** React security symbol — see https://github.com/facebook/react/pull/4832 */
6
5
  const $$typeof = Symbol.for("react.element");
7
6
  /**
@@ -10,13 +9,14 @@ const $$typeof = Symbol.for("react.element");
10
9
  * - Same as Markdown syntax.
11
10
  * - Markdown's underline syntax is not supported (for simplification).
12
11
  */
13
- export const HEADING_RULE = new NamedRegExpMarkupRule(getLineRegExp(`(?<prefix>#{1,6}) +(?<heading>${LINE_REGEXP.source})`), ({ prefix, heading }) => ({
12
+ export const HEADING_RULE = getNamedMarkupRule(getLineRegExp(`(?<prefix>#{1,6}) +(?<heading>${LINE_REGEXP.source})`), ({ prefix, heading }) => ({
14
13
  type: `h${prefix.length}`,
15
14
  key: null,
16
15
  ref: null,
17
16
  $$typeof,
18
17
  props: { children: heading.trim() },
19
- }), ["block"], "inline");
18
+ context: "inline",
19
+ }), ["block"]);
20
20
  /**
21
21
  * Separator (horizontal rule / thematic break).
22
22
  * - Same as Markdown syntax but also allows `•` bullet character (in addition to `-` dash, `+` plus, `*` asterisk, `_` underscore).
@@ -24,7 +24,7 @@ export const HEADING_RULE = new NamedRegExpMarkupRule(getLineRegExp(`(?<prefix>#
24
24
  * - Character must be the same every time (can't mix)
25
25
  * - Might have infinite number of spaces between the characters.
26
26
  */
27
- export const SEPARATOR_RULE = new RegExpMarkupRule(getLineRegExp("([-*•+_=])(?: *\\1){2,}"), () => ({
27
+ export const SEPARATOR_RULE = getMarkupRule(getLineRegExp("([-*•+_=])(?: *\\1){2,}"), () => ({
28
28
  type: "hr",
29
29
  key: null,
30
30
  ref: null,
@@ -41,13 +41,14 @@ export const SEPARATOR_RULE = new RegExpMarkupRule(getLineRegExp("([-*•+_=])(?
41
41
  const UNORDERED_PREFIX = "[-*•+] +";
42
42
  const UNORDERED_SPLIT = new RegExp(`(?:^|\n)+${UNORDERED_PREFIX}`, "g");
43
43
  const UNORDERED_INDENT = /^\t/gm;
44
- export const UNORDERED_RULE = new NamedRegExpMarkupRule(getBlockRegExp(`(?<list>${UNORDERED_PREFIX}${BLOCK_REGEXP.source})`), ({ list }) => ({
44
+ export const UNORDERED_RULE = getNamedMarkupRule(getBlockRegExp(`(?<list>${UNORDERED_PREFIX}${BLOCK_REGEXP.source})`), ({ list }) => ({
45
45
  type: "ul",
46
46
  key: null,
47
47
  ref: null,
48
48
  $$typeof,
49
49
  props: { children: list.split(UNORDERED_SPLIT).filter(Boolean).map(_mapUnordered) },
50
- }), ["block", "list"], "list");
50
+ context: "list",
51
+ }), ["block", "list"]);
51
52
  const _mapUnordered = (item, key) => ({
52
53
  type: "li",
53
54
  key,
@@ -63,13 +64,14 @@ const _mapUnordered = (item, key) => ({
63
64
  const ORDERED_PREFIX = "[1-9][0-9]{0,8}[.):] +"; // Number for a numbered list, e.g. `1.` or `2)` or `3:`
64
65
  const ORDERED_SPLIT = new RegExp(`\n+(?=${ORDERED_PREFIX})`, "g");
65
66
  const ORDERED_INDENT = UNORDERED_INDENT;
66
- export const ORDERED_RULE = new NamedRegExpMarkupRule(getBlockRegExp(`(?<list>${ORDERED_PREFIX}${BLOCK_REGEXP.source})`), ({ list }) => ({
67
+ export const ORDERED_RULE = getNamedMarkupRule(getBlockRegExp(`(?<list>${ORDERED_PREFIX}${BLOCK_REGEXP.source})`), ({ list }) => ({
67
68
  type: "ol",
68
69
  key: null,
69
70
  ref: null,
70
71
  $$typeof,
71
72
  props: { children: list.split(ORDERED_SPLIT).map(_mapOrdered) },
72
- }), ["block", "list"], "list");
73
+ context: "list",
74
+ }), ["block", "list"]);
73
75
  const _mapOrdered = (item, key) => ({
74
76
  type: "li",
75
77
  key,
@@ -91,13 +93,14 @@ const _mapOrdered = (item, key) => ({
91
93
  */
92
94
  const BLOCKQUOTE_PREFIX = "> *";
93
95
  const BLOCKQUOTE_INDENT = new RegExp(`^${BLOCKQUOTE_PREFIX}`, "gm");
94
- export const BLOCKQUOTE_RULE = new NamedRegExpMarkupRule(getLineRegExp(`(?<quote>${BLOCKQUOTE_PREFIX}${LINE_REGEXP.source}(?:\n${BLOCKQUOTE_PREFIX}${LINE_REGEXP.source})*)`), ({ quote }) => ({
96
+ export const BLOCKQUOTE_RULE = getNamedMarkupRule(getLineRegExp(`(?<quote>${BLOCKQUOTE_PREFIX}${LINE_REGEXP.source}(?:\n${BLOCKQUOTE_PREFIX}${LINE_REGEXP.source})*)`), ({ quote }) => ({
95
97
  type: "blockquote",
96
98
  key: null,
97
99
  ref: null,
98
100
  $$typeof,
99
101
  props: { children: quote.replace(BLOCKQUOTE_INDENT, "") },
100
- }), ["block", "list"], "block");
102
+ context: "block",
103
+ }), ["block", "list"]);
101
104
  /**
102
105
  * Fenced code blocks
103
106
  * - Same as Markdown syntax.
@@ -105,7 +108,7 @@ export const BLOCKQUOTE_RULE = new NamedRegExpMarkupRule(getLineRegExp(`(?<quote
105
108
  * - If there's no closing fence the code block will run to the end of the current string.
106
109
  * - Markdown-style four-space indent syntax is not supported (only fenced code, since it's easier to use).
107
110
  */
108
- export const FENCED_CODE_RULE = new NamedRegExpMarkupRule(
111
+ export const FENCED_CODE_RULE = getNamedMarkupRule(
109
112
  // Matcher has its own end that only stops when it reaches a matching closing fence or the end of the string.
110
113
  getLineRegExp(`(?<wrap>\`{3,}|~{3,}) *(?<title>${LINE_REGEXP.source})\n(?<code>${BLOCK_REGEXP.source})`, `(?:\n\\k<wrap>|$)`), ({ title, code }) => ({
111
114
  type: "pre",
@@ -121,26 +124,28 @@ getLineRegExp(`(?<wrap>\`{3,}|~{3,}) *(?<title>${LINE_REGEXP.source})\n(?<code>$
121
124
  props: { title: title?.trim() || undefined, children: code.trim() },
122
125
  },
123
126
  },
124
- }), ["block", "list"], null, 10);
127
+ }), ["block", "list"], 10);
125
128
  /**
126
129
  * Paragraph.
127
130
  * - When ordering rules, paragraph should go after other "block" context elements (because it has a very generous capture).
128
131
  */
129
- export const PARAGRAPH_RULE = new NamedRegExpMarkupRule(getBlockRegExp(`(?<paragraph>${BLOCK_REGEXP.source})`), ({ paragraph }) => ({
132
+ export const PARAGRAPH_RULE = getNamedMarkupRule(getBlockRegExp(`(?<paragraph>${BLOCK_REGEXP.source})`), ({ paragraph }) => ({
130
133
  type: `p`,
131
134
  key: null,
132
135
  ref: null,
133
136
  $$typeof,
134
137
  props: { children: paragraph.trim() },
135
- }), ["block"], "inline", -10);
138
+ context: "inline",
139
+ }), ["block"], -10);
136
140
  /** Render function for URL and LINK rules. */
137
- export function renderLinkRule({ href, title }, { rel }) {
141
+ export function renderLinkRule(title, href, { rel }) {
138
142
  return {
139
143
  type: "a",
140
144
  key: null,
141
145
  ref: null,
142
146
  $$typeof,
143
147
  props: { children: title, href, rel },
148
+ context: "link",
144
149
  };
145
150
  }
146
151
  /**
@@ -150,8 +155,8 @@ export function renderLinkRule({ href, title }, { rel }) {
150
155
  * - If link is not valid (using `new URL(url)` then unparsed text will be returned.
151
156
  * - For security only schemes that appear in `options.schemes` will match (defaults to `http:` and `https:`).
152
157
  */
153
- export const URL_RULE = new LinkRegExpMarkupRule(getRegExp(/(?<href>[a-z]+:[-$_@.&!*,=;/#?:%a-zA-Z0-9]+)(?: +(?:\((?<title>[^)]*?)\)))?/), //
154
- renderLinkRule, ["inline", "list"], "link");
158
+ export const URL_RULE = getLinkMarkupRule(getRegExp(/(?<href>[a-z]+:[-$_@.&!*,=;/#?:%a-zA-Z0-9]+)(?: +(?:\((?<title>[^)]*?)\)))?/), //
159
+ renderLinkRule, ["inline", "list"]);
155
160
  /**
156
161
  * Markdown-style link.
157
162
  * - Link in standard Markdown format, e.g. `[Google Maps](http://google.com/maps)`
@@ -160,8 +165,8 @@ renderLinkRule, ["inline", "list"], "link");
160
165
  * - If link is not valid (using `new URL(url)` then unparsed text will be returned.
161
166
  * - For security only `http://` or `https://` links will work (if invalid the unparsed text will be returned).
162
167
  */
163
- export const LINK_RULE = new LinkRegExpMarkupRule(getRegExp(/\[(?<title>[^\]]*?)\]\((?<href>[^)]*?)\)/), //
164
- renderLinkRule, ["inline", "list"], "link");
168
+ export const LINK_RULE = getLinkMarkupRule(getRegExp(/\[(?<title>[^\]]*?)\]\((?<href>[^)]*?)\)/), //
169
+ renderLinkRule, ["inline", "list"]);
165
170
  /**
166
171
  * Inline code.
167
172
  * - Text surrounded by one or more "`" backtick tilde characters.
@@ -169,13 +174,13 @@ renderLinkRule, ["inline", "list"], "link");
169
174
  * - Closing characters must exactly match opening characters.
170
175
  * - Same as Markdown syntax.
171
176
  */
172
- export const CODE_RULE = new NamedRegExpMarkupRule(new RegExp(`(?<wrap>\`+)(?<code>${BLOCK_REGEXP.source})\\k<wrap>`), ({ code }) => ({
177
+ export const CODE_RULE = getNamedMarkupRule(new RegExp(`(?<wrap>\`+)(?<code>${BLOCK_REGEXP.source})\\k<wrap>`), ({ code }) => ({
173
178
  type: "code",
174
179
  key: null,
175
180
  ref: null,
176
181
  $$typeof,
177
182
  props: { children: code },
178
- }), ["inline", "list"], null, 10);
183
+ }), ["inline", "list"], 10);
179
184
  /**
180
185
  * Inline strong, emphasis, insert, delete, highlight.
181
186
  * - Inline strong text wrapped in one or more `*` asterisks.
@@ -190,14 +195,15 @@ export const CODE_RULE = new NamedRegExpMarkupRule(new RegExp(`(?<wrap>\`+)(?<co
190
195
  * - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
191
196
  */
192
197
  const INLINE_CHARS = { "-": "del", "~": "del", "+": "ins", "*": "strong", "_": "em", "=": "mark", ":": "mark" }; // Hyphen must be first so it works when we use the keys as a character class.
193
- export const INLINE_RULE = new NamedRegExpMarkupRule(new WordRegExp(`(?<wrap>(?<char>[${Object.keys(INLINE_CHARS).join("")}])+)(?<text>(?!\\k<char>)\\S|(?!\\k<char>)\\S[\\s\\S]*?(?!\\k<char>)\\S)\\k<wrap>`), // prettier-ignore
198
+ export const INLINE_RULE = getNamedMarkupRule(new WordRegExp(`(?<wrap>(?<char>[${Object.keys(INLINE_CHARS).join("")}])+)(?<text>(?!\\k<char>)\\S|(?!\\k<char>)\\S[\\s\\S]*?(?!\\k<char>)\\S)\\k<wrap>`), // prettier-ignore
194
199
  ({ char, text }) => ({
195
200
  type: INLINE_CHARS[char],
196
201
  key: null,
197
202
  ref: null,
198
203
  $$typeof,
199
204
  props: { children: text },
200
- }), ["inline", "list", "link"], "inline");
205
+ context: "inline",
206
+ }), ["inline", "list", "link"]);
201
207
  /**
202
208
  * Hard linebreak (`<br />` tag).
203
209
  * - Any line break in a paragraph will become a hard `<br />` tag.
@@ -206,13 +212,13 @@ export const INLINE_RULE = new NamedRegExpMarkupRule(new WordRegExp(`(?<wrap>(?<
206
212
  * - This is more intuitive (a linebreak becomes a linebreak is isn't silently ignored).
207
213
  * - This works better with textareas that wrap text (since manually breaking up long lines is no longer necessary).
208
214
  */
209
- export const LINEBREAK_RULE = new RegExpMarkupRule(/\n/, () => ({
215
+ export const LINEBREAK_RULE = getMarkupRule(/\n/, () => ({
210
216
  type: "br",
211
217
  key: null,
212
218
  ref: null,
213
219
  $$typeof,
214
220
  props: {},
215
- }), ["inline", "list", "link"], "inline");
221
+ }), ["inline", "list", "link"]);
216
222
  /**
217
223
  * All markup rules.
218
224
  * - Syntax parsed by `renderMarkup()` is defined entirely by the list of rules (i.e. not by code).
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.110.0",
14
+ "version": "1.110.1",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
package/util/regexp.d.ts CHANGED
@@ -6,18 +6,6 @@ export declare const ALWAYS_REGEXP: RegExp;
6
6
  export declare const NEVER_REGEXP: RegExp;
7
7
  /** Things that can be convert to a regular expression. */
8
8
  export type PossibleRegExp = string | RegExp;
9
- /** Set of named match groups from a regular expression. */
10
- export type NamedRegExpData = {
11
- [named: string]: string;
12
- };
13
- /** Regular expression match array that you've asserted contains the specified named groups. */
14
- export interface NamedRegExpArray<T extends NamedRegExpData = NamedRegExpData> extends RegExpExecArray {
15
- groups: T;
16
- }
17
- /** Regular expression that you've asserted contains the specified named capture groups. */
18
- export interface NamedRegExp<T extends NamedRegExpData = NamedRegExpData> extends RegExp {
19
- exec(input: string): NamedRegExpArray<T> | null;
20
- }
21
9
  /** Is an unknown value a `RegExp` instance? */
22
10
  export declare const isRegExp: (value: unknown) => value is RegExp;
23
11
  /** Assert that an unknown value is a `RegExp` instance. */
@@ -39,3 +27,23 @@ export declare function getAllRegExp(patterns: Iterable<PossibleRegExp> & NotStr
39
27
  export declare const isRegExpMatch: Match<[item: string, target: RegExp]>;
40
28
  /** Match function for finding strings that match against regular expressions (use with `filter()` to negatively filter iterable sets of items). */
41
29
  export declare const notRegExpMatch: Match<[item: string, target: RegExp]>;
30
+ /** Regular expression match array that you've asserted contains the specified named groups. */
31
+ export interface TypedRegExpExecArray<T extends string = string> extends RegExpExecArray {
32
+ 0: T;
33
+ }
34
+ /** Regular expression that you've asserted contains the specified named capture groups. */
35
+ export interface TypedRegExp<T extends string = string> extends RegExp {
36
+ exec(input: string): TypedRegExpExecArray<T> | null;
37
+ }
38
+ /** Set of named match groups from a regular expression. */
39
+ export type NamedRegExpData = {
40
+ [named: string]: string;
41
+ };
42
+ /** Regular expression match array that you've asserted contains the specified named groups. */
43
+ export interface NamedRegExpExecArray<T extends NamedRegExpData = NamedRegExpData> extends RegExpExecArray {
44
+ groups: T;
45
+ }
46
+ /** Regular expression that you've asserted contains the specified named capture groups. */
47
+ export interface NamedRegExp<T extends NamedRegExpData = NamedRegExpData> extends RegExp {
48
+ exec(input: string): NamedRegExpExecArray<T> | null;
49
+ }