shelving 1.128.2 → 1.129.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.
Files changed (73) hide show
  1. package/iterate/{AbstractGenerator.d.ts → AbstractIterator.d.ts} +2 -3
  2. package/iterate/{AbstractGenerator.js → AbstractIterator.js} +1 -2
  3. package/iterate/{InspectGenerator.d.ts → InspectIterator.d.ts} +3 -3
  4. package/iterate/{InspectGenerator.js → InspectIterator.js} +3 -3
  5. package/iterate/{ThroughGenerator.d.ts → ThroughIterator.d.ts} +2 -2
  6. package/iterate/{ThroughGenerator.js → ThroughIterator.js} +3 -3
  7. package/iterate/index.d.ts +3 -3
  8. package/iterate/index.js +3 -3
  9. package/markup/index.d.ts +4 -4
  10. package/markup/index.js +5 -4
  11. package/markup/render.d.ts +3 -26
  12. package/markup/render.js +41 -97
  13. package/markup/rule/blockquote.d.ts +8 -0
  14. package/markup/rule/blockquote.js +19 -0
  15. package/markup/rule/code.d.ts +8 -0
  16. package/markup/rule/code.js +18 -0
  17. package/markup/rule/fenced.d.ts +10 -0
  18. package/markup/rule/fenced.js +34 -0
  19. package/markup/rule/heading.d.ts +7 -0
  20. package/markup/rule/heading.js +17 -0
  21. package/markup/rule/index.d.ts +44 -0
  22. package/markup/rule/index.js +63 -0
  23. package/markup/rule/inline.d.ts +14 -0
  24. package/markup/rule/inline.js +26 -0
  25. package/markup/rule/linebreak.d.ts +11 -0
  26. package/markup/rule/linebreak.js +18 -0
  27. package/markup/rule/link.d.ts +24 -0
  28. package/markup/rule/link.js +40 -0
  29. package/markup/rule/ordered.d.ts +11 -0
  30. package/markup/rule/ordered.js +39 -0
  31. package/markup/rule/paragraph.d.ts +10 -0
  32. package/markup/rule/paragraph.js +19 -0
  33. package/markup/rule/separator.d.ts +8 -0
  34. package/markup/rule/separator.js +17 -0
  35. package/markup/rule/unordered.d.ts +16 -0
  36. package/markup/rule/unordered.js +39 -0
  37. package/markup/util/internal.d.ts +2 -0
  38. package/markup/util/internal.js +2 -0
  39. package/markup/util/options.d.ts +28 -0
  40. package/markup/util/options.js +1 -0
  41. package/markup/util/regexp.d.ts +21 -0
  42. package/markup/util/regexp.js +21 -0
  43. package/markup/util/rule.d.ts +17 -0
  44. package/markup/util/rule.js +9 -0
  45. package/package.json +11 -11
  46. package/sequence/AbstractSequence.d.ts +2 -2
  47. package/sequence/DeferredSequence.d.ts +1 -1
  48. package/sequence/InspectSequence.d.ts +3 -3
  49. package/sequence/InspectSequence.js +2 -2
  50. package/sequence/LazyDeferredSequence.d.ts +1 -1
  51. package/sequence/ThroughSequence.d.ts +1 -1
  52. package/test/basics.d.ts +4 -4
  53. package/test/index.d.ts +6 -6
  54. package/test/people.d.ts +2 -2
  55. package/test/util.d.ts +6 -9
  56. package/test/util.js +14 -53
  57. package/util/error.d.ts +2 -0
  58. package/util/error.js +20 -0
  59. package/util/jsx.d.ts +6 -7
  60. package/util/link.d.ts +21 -4
  61. package/util/link.js +3 -3
  62. package/util/object.d.ts +1 -1
  63. package/util/regexp.d.ts +2 -4
  64. package/util/units.d.ts +1 -1
  65. package/util/units.js +2 -1
  66. package/markup/options.d.ts +0 -19
  67. package/markup/options.js +0 -10
  68. package/markup/regexp.d.ts +0 -28
  69. package/markup/regexp.js +0 -19
  70. package/markup/rule.d.ts +0 -62
  71. package/markup/rule.js +0 -67
  72. package/markup/rules.d.ts +0 -141
  73. package/markup/rules.js +0 -277
@@ -1,8 +1,7 @@
1
1
  /** Abstract generator designed to be extended that implements the full generator protocol. */
2
- export declare abstract class AbstractGenerator<T, R, N> implements Generator<T, R, N> {
3
- readonly [Symbol.toStringTag] = "Generator";
2
+ export declare abstract class AbstractIterator<T, R, N> implements Iterator<T, R, N>, Iterable<T, R, N> {
4
3
  abstract next(value: N): IteratorResult<T, R>;
5
4
  throw(thrown: unknown): IteratorResult<T, R>;
6
5
  return(value: R): IteratorResult<T, R>;
7
- [Symbol.iterator](): Generator<T, R, N>;
6
+ [Symbol.iterator](): Iterator<T, R, N>;
8
7
  }
@@ -1,6 +1,5 @@
1
1
  /** Abstract generator designed to be extended that implements the full generator protocol. */
2
- export class AbstractGenerator {
3
- [Symbol.toStringTag] = "Generator";
2
+ export class AbstractIterator {
4
3
  throw(thrown) {
5
4
  // Default behaviour for a generator is to throw the error back out of the iterator and not continue.
6
5
  throw thrown;
@@ -1,15 +1,15 @@
1
- import { ThroughGenerator } from "./ThroughGenerator.js";
1
+ import { ThroughIterator } from "./ThroughIterator.js";
2
2
  /**
3
3
  * Iterable that inspects a source iterable as it iterates.
4
4
  * - Stores: first/last yielded value, returned value, whether iteration is done, the number of items that were iterated.
5
5
  *
6
6
  * @example
7
- * const watch = new WatchIterator(iterable);
7
+ * const watch = new InspectIterator(iterable);
8
8
  * for (const next of capture) console.log("YIELDED", next);
9
9
  * console.log("FIRST", watch.first);
10
10
  * console.log("RETURNED", watch.returned);
11
11
  */
12
- export declare class InspectGenerator<T, R, N> extends ThroughGenerator<T, R, N> {
12
+ export declare class InspectIterator<T, R, N> extends ThroughIterator<T, R, N> implements Iterator<T, R, N>, Iterable<T, R, N> {
13
13
  /** Get the number of results received by this iterator so far. */
14
14
  readonly count = 0;
15
15
  /** Is the iteration done? */
@@ -1,5 +1,5 @@
1
1
  import { StateError } from "../error/StateError.js";
2
- import { ThroughGenerator } from "./ThroughGenerator.js";
2
+ import { ThroughIterator } from "./ThroughIterator.js";
3
3
  /** Used when the sequence hasn't inspected anything yet. */
4
4
  const _NOVALUE = Symbol("shelving/InspectGenerator.NOVALUE");
5
5
  /**
@@ -7,12 +7,12 @@ const _NOVALUE = Symbol("shelving/InspectGenerator.NOVALUE");
7
7
  * - Stores: first/last yielded value, returned value, whether iteration is done, the number of items that were iterated.
8
8
  *
9
9
  * @example
10
- * const watch = new WatchIterator(iterable);
10
+ * const watch = new InspectIterator(iterable);
11
11
  * for (const next of capture) console.log("YIELDED", next);
12
12
  * console.log("FIRST", watch.first);
13
13
  * console.log("RETURNED", watch.returned);
14
14
  */
15
- export class InspectGenerator extends ThroughGenerator {
15
+ export class InspectIterator extends ThroughIterator {
16
16
  /** Get the number of results received by this iterator so far. */
17
17
  count = 0;
18
18
  /** Is the iteration done? */
@@ -1,6 +1,6 @@
1
- import { AbstractGenerator } from "./AbstractGenerator.js";
1
+ import { AbstractIterator } from "./AbstractIterator.js";
2
2
  /** Iterable that pulls values from a source iterable. */
3
- export declare class ThroughGenerator<T, R, N> extends AbstractGenerator<T, R, N> {
3
+ export declare class ThroughIterator<T, R, N> extends AbstractIterator<T, R, N> implements Iterator<T, R, N>, Iterable<T, R, N> {
4
4
  private readonly _source;
5
5
  constructor(iterator: Iterator<T, R, N>);
6
6
  next(value: N): IteratorResult<T, R>;
@@ -1,12 +1,12 @@
1
- import { AbstractGenerator } from "./AbstractGenerator.js";
1
+ import { AbstractIterator } from "./AbstractIterator.js";
2
2
  /** Iterable that pulls values from a source iterable. */
3
- export class ThroughGenerator extends AbstractGenerator {
3
+ export class ThroughIterator extends AbstractIterator {
4
4
  _source;
5
5
  constructor(iterator) {
6
6
  super();
7
7
  this._source = iterator;
8
8
  }
9
- // Implement `AbstractGenerator`
9
+ // Implement `AbstractIterator`
10
10
  next(value) {
11
11
  return this._source.next(value);
12
12
  }
@@ -1,3 +1,3 @@
1
- export * from "./AbstractGenerator.js";
2
- export * from "./ThroughGenerator.js";
3
- export * from "./InspectGenerator.js";
1
+ export * from "./AbstractIterator.js";
2
+ export * from "./ThroughIterator.js";
3
+ export * from "./InspectIterator.js";
package/iterate/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export * from "./AbstractGenerator.js";
2
- export * from "./ThroughGenerator.js";
3
- export * from "./InspectGenerator.js";
1
+ export * from "./AbstractIterator.js";
2
+ export * from "./ThroughIterator.js";
3
+ export * from "./InspectIterator.js";
package/markup/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export * from "./options.js";
2
- export * from "./rule.js";
3
- export * from "./rules.js";
1
+ export * from "./util/options.js";
2
+ export * from "./util/rule.js";
3
+ export * from "./util/regexp.js";
4
+ export * from "./rule/index.js";
4
5
  export * from "./render.js";
5
- export * from "./regexp.js";
package/markup/index.js CHANGED
@@ -1,5 +1,6 @@
1
- export * from "./options.js";
2
- export * from "./rule.js";
3
- export * from "./rules.js";
1
+ export * from "./util/options.js";
2
+ export * from "./util/rule.js";
3
+ export * from "./util/regexp.js";
4
+ // export * from "./util/internal.js"; // Not exported.
5
+ export * from "./rule/index.js";
4
6
  export * from "./render.js";
5
- export * from "./regexp.js";
@@ -1,36 +1,13 @@
1
1
  import type { JSXNode } from "../util/jsx.js";
2
- import type { MarkupOptions } from "./options.js";
2
+ import type { MarkupOptions } from "./util/options.js";
3
3
  /**
4
4
  * Parse a text string as Markdownish syntax and render it as a JSX node.
5
5
  * - Syntax is not defined by this code, but by the rules supplied to it.
6
- * - Default rules define syntax similar to Markdown but with improvements:
7
- * 1. Syntax is more intuitive (e.g. `*strong*` always uses `*` asterisk and `_em_` always uses `_` underscore, and URLs are always autolinked).
8
- * 2. More compatible with textboxes that wrap lines by default (e.g. single `\n` linebreaks don't need the trailing double space to, they're always treated as `<br />`).
9
- * 3. Don't support fussy fragile syntax that lets users make mistakes (e.g. literal HTML tags or `&amp;` character entities).
10
- *
11
- * DH: This code is heavily inspired by `simple-markdown`, but intends to be even simpler by always producing JSX elements.
12
- *
13
- * @todo [ ] Default rules support "list items containing paragraphs" syntax (CommonMark calls this loose lists).
14
- * - i.e. Lists can include `\n\n` double line breaks, and wrap all their contents in `<p>` entities, i.e. childContext is "block"
15
- * - Hard because you have to capture the entire list including `\n\n`, so there's no obvious place to end it.
16
- * - If there are breaks then any sub-lines need to be indented by two or more spaces otherwise it will break the list.
17
- * - Make reference lists support this loose format too.
18
- * @todo [ ] Default rules support tables using `|` pipe syntax.
19
- * @todo [ ] Default rules support todo lists using `- [x]` syntax.
20
- * @todo [ ] Default rules support new reference syntax (combines reference lists/sidenotes/footnotes/reference and produces <dl> syntax).
21
- * - All of these can be the same because reference links and Extended Markdown footnotes are basically the same.
22
- * - e.g. `[Google Maps][1]` → `[1]: http://google.com Content goes here` (Markdown reference link syntax).
23
- * - e.g. `[Google Maps]` → `[Google Maps]: http://google.com Content goes here` syntax.
24
- * - e.g. `[DNS]` → `[DNS]: Domain Name System (extended Markdown definition list format).
25
- * - If a `[Reference]` does not correspond to anything it will not be linked and e.g. will appear unlinked.
26
- * - Single/double quotes around definition part are optional and are trimmed from the start/end (Extended Markdown definition lists require quotes, but that's dumb).
27
- * - A `<dl>` definition list is used as the output format for all of these different use cases.
28
- * - If the first thing in the definition is a URL, then it's recognised as a link reference (and produces an `<a href=""></a>`)
29
- * - If the first thing in the definition isn't a URL, then it's recognised as a sidenote/footnote and tapping it will scroll you to that point (and popup the definition like Marco Arment's Bigfoot code).
30
6
  *
31
7
  * @param input The string content possibly containing markup syntax, e.g. "This is a *bold* string.
32
8
  * @param options An options object for the render.
9
+ * @param context The context to render in (defaults to `"block"`).
33
10
  *
34
11
  * @returns JSXNode, i.e. either a complete `JSXElement`, `null`, `undefined`, `string`, or an array of zero or more of those.
35
12
  */
36
- export declare function renderMarkup(input: string, options?: Partial<MarkupOptions>): JSXNode;
13
+ export declare function renderMarkup(input: string, options: MarkupOptions, context?: string): JSXNode;
package/markup/render.js CHANGED
@@ -1,119 +1,63 @@
1
- import { isArray } from "../util/array.js";
2
- import { mapArray } from "../util/transform.js";
3
- import { MARKUP_OPTIONS } from "./options.js";
4
1
  /**
5
2
  * Parse a text string as Markdownish syntax and render it as a JSX node.
6
3
  * - Syntax is not defined by this code, but by the rules supplied to it.
7
- * - Default rules define syntax similar to Markdown but with improvements:
8
- * 1. Syntax is more intuitive (e.g. `*strong*` always uses `*` asterisk and `_em_` always uses `_` underscore, and URLs are always autolinked).
9
- * 2. More compatible with textboxes that wrap lines by default (e.g. single `\n` linebreaks don't need the trailing double space to, they're always treated as `<br />`).
10
- * 3. Don't support fussy fragile syntax that lets users make mistakes (e.g. literal HTML tags or `&amp;` character entities).
11
- *
12
- * DH: This code is heavily inspired by `simple-markdown`, but intends to be even simpler by always producing JSX elements.
13
- *
14
- * @todo [ ] Default rules support "list items containing paragraphs" syntax (CommonMark calls this loose lists).
15
- * - i.e. Lists can include `\n\n` double line breaks, and wrap all their contents in `<p>` entities, i.e. childContext is "block"
16
- * - Hard because you have to capture the entire list including `\n\n`, so there's no obvious place to end it.
17
- * - If there are breaks then any sub-lines need to be indented by two or more spaces otherwise it will break the list.
18
- * - Make reference lists support this loose format too.
19
- * @todo [ ] Default rules support tables using `|` pipe syntax.
20
- * @todo [ ] Default rules support todo lists using `- [x]` syntax.
21
- * @todo [ ] Default rules support new reference syntax (combines reference lists/sidenotes/footnotes/reference and produces <dl> syntax).
22
- * - All of these can be the same because reference links and Extended Markdown footnotes are basically the same.
23
- * - e.g. `[Google Maps][1]` → `[1]: http://google.com Content goes here` (Markdown reference link syntax).
24
- * - e.g. `[Google Maps]` → `[Google Maps]: http://google.com Content goes here` syntax.
25
- * - e.g. `[DNS]` → `[DNS]: Domain Name System (extended Markdown definition list format).
26
- * - If a `[Reference]` does not correspond to anything it will not be linked and e.g. will appear unlinked.
27
- * - Single/double quotes around definition part are optional and are trimmed from the start/end (Extended Markdown definition lists require quotes, but that's dumb).
28
- * - A `<dl>` definition list is used as the output format for all of these different use cases.
29
- * - If the first thing in the definition is a URL, then it's recognised as a link reference (and produces an `<a href=""></a>`)
30
- * - If the first thing in the definition isn't a URL, then it's recognised as a sidenote/footnote and tapping it will scroll you to that point (and popup the definition like Marco Arment's Bigfoot code).
31
4
  *
32
5
  * @param input The string content possibly containing markup syntax, e.g. "This is a *bold* string.
33
6
  * @param options An options object for the render.
7
+ * @param context The context to render in (defaults to `"block"`).
34
8
  *
35
9
  * @returns JSXNode, i.e. either a complete `JSXElement`, `null`, `undefined`, `string`, or an array of zero or more of those.
36
10
  */
37
- export function renderMarkup(input, options) {
38
- if (!input)
39
- return null;
40
- const combined = options ? { ...MARKUP_OPTIONS, ...options } : MARKUP_OPTIONS;
41
- return _renderString(input, combined, combined.context);
42
- }
43
- /**
44
- * Render a string to its corresponding JSX node in a given context.
45
- */
46
- function _renderString(input, options, context) {
47
- const nodes = Array.from(_parseString(input, options, context));
48
- return !nodes.length ? null : nodes.length === 1 ? nodes[0] : nodes;
49
- }
50
- /**
51
- * Render a JSX node in a given context.
52
- */
53
- function _renderNode(node, options, context) {
54
- if (!node)
55
- return node;
56
- if (typeof node === "string")
57
- return _renderString(node, options, context);
58
- if (isArray(node))
59
- return mapArray(node, _renderNode, options, context);
60
- return _renderElement(node, options, context);
61
- }
62
- /**
63
- * Render a JSX element in a given context.
64
- */
65
- function _renderElement(element, options, context) {
66
- element.props.children = _renderNode(element.props.children, options, context);
67
- return element;
11
+ export function renderMarkup(input, options, context = "block") {
12
+ const arr = Array.from(_parseString(input, options, context));
13
+ return !arr.length ? null : arr.length === 1 ? arr[0] : arr;
68
14
  }
69
15
  /**
70
16
  * Parse a string to its corresponding JSX nodes in a given context.
71
- *
72
- * @param offset Keeps track of where we are within the wider string we're parsing when we're several calls deep.
17
+ * - This code is heavily inspired by `simple-markdown`, but intends to be even simpler (and faster) by always producing JSX elements.
73
18
  */
74
- function* _parseString(input, options, outerContext, offset = 0) {
75
- let element = undefined;
76
- let highPriority = Number.MIN_SAFE_INTEGER;
77
- let lowIndex = Number.MIN_SAFE_INTEGER;
19
+ function* _parseString(
20
+ /** The input string. */
21
+ input,
22
+ /** Options that configure the render including the rules we're using. */
23
+ options,
24
+ /** The context for the render e.g. `"block"` */
25
+ context,
26
+ /** The offset of where we are in the _original_ string — this is used to compute the `key` property for the returned element. */
27
+ offset = 0) {
28
+ // The best matched rule is the one with the highest priority.
29
+ // If two have equal priority use the earliest match in the string.
30
+ let bestMatch = undefined;
31
+ let bestRule = undefined;
78
32
  // Loop through all rules in the list and see if any match.
79
33
  for (const rule of options.rules) {
80
- // Only apply this rule if both:
81
- // 1. The priority is equal or higher to the current priority.
82
- // 2. The rule is allowed in the current context.
83
- const { priority = 0, contexts } = rule;
84
- if (priority >= highPriority && contexts.includes(outerContext)) {
85
- const match = rule.match(input, options);
86
- if (match) {
87
- // Use the match if it has length and is earlier in the string or is higher priority.
88
- const { index, length } = match;
89
- if (length && (index < lowIndex || priority > highPriority)) {
90
- element = match;
91
- highPriority = priority;
92
- lowIndex = index;
93
- }
34
+ const { priority, regexp, contexts } = rule;
35
+ // Skip rule if it has lower priority than the current best rule, or it doesn't apply in this context.
36
+ if ((!bestRule || priority >= bestRule.priority) && contexts.includes(context)) {
37
+ const match = regexp.exec(input);
38
+ // This rule is the best rule if it matches, has higher priority than the current best rule, or is earlier in the string than the current best rule.
39
+ if (match && (!bestRule || !bestMatch || priority > bestRule.priority || match.index < bestMatch.index)) {
40
+ bestRule = rule;
41
+ bestMatch = match;
94
42
  }
95
43
  }
96
44
  }
97
- // Did at least one rule match?
98
- if (element) {
99
- // If index is more than zero, then the string before the match may match another rule at lower priority.
100
- const prefix = input.slice(0, lowIndex);
101
- if (prefix.length)
102
- yield* _parseString(prefix, options, outerContext, offset);
103
- // Call the rule's `render()` function to generate the node.
104
- // React gets annoyed if we don't set a `key:` property on lists of elements.
105
- // 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.
106
- // Trying to generate an incrementing number would require tracking the number and passing it back and forth through `_parseString()`
107
- const { index, length, context } = element;
108
- element.key = (offset + index).toString();
109
- yield context ? _renderElement(element, options, context) : element;
110
- // Decrement the content.
111
- const suffix = input.slice(index + length);
112
- if (suffix.length)
113
- yield* _parseString(suffix, options, outerContext, offset + index + length);
45
+ // Was there a matching rule?
46
+ if (bestRule && bestMatch) {
47
+ const { index, 0: { length }, } = bestMatch;
48
+ const end = bestMatch.index + length;
49
+ // Parse the prefix and yield any elements.
50
+ if (bestMatch.index > 0)
51
+ yield* _parseString(input.slice(0, bestMatch.index), options, context);
52
+ // Yield the matched element.
53
+ yield bestRule.render(bestMatch, options, (offset + index).toString());
54
+ // Parse the suffix and yield any elements.
55
+ // Pass `end` as `offset` so that `key` for any yielded elements acknowledges its increased position in the string.
56
+ if (input.length > end)
57
+ yield* _parseString(input.slice(end), options, context, end);
114
58
  }
115
- else {
116
- // If nothing matched return the entire string..
59
+ else if (input.length) {
60
+ // Nothing matched so return the entire string because this is a text node.
117
61
  yield input;
118
62
  }
119
63
  }
@@ -0,0 +1,8 @@
1
+ export declare const BLOCKQUOTE_REGEXP: RegExp;
2
+ /**
3
+ * Blockquote block.
4
+ * - `>` quote character followed by zero or more spaces.
5
+ * - No spaces can appear before the `>` quote character.
6
+ * - Quote block is only broken by `\n\n` two newline characters.
7
+ */
8
+ export declare const BLOCKQUOTE_RULE: import("../util/rule.js").MarkupRule;
@@ -0,0 +1,19 @@
1
+ import { renderMarkup } from "../render.js";
2
+ import { REACT_ELEMENT_TYPE } from "../util/internal.js";
3
+ import { BLOCK_CONTENT_REGEXP, getBlockRegExp } from "../util/regexp.js";
4
+ import { getMarkupRule } from "../util/rule.js";
5
+ const PREFIX = ">";
6
+ const INDENT = new RegExp(`^${PREFIX}`, "gm");
7
+ export const BLOCKQUOTE_REGEXP = getBlockRegExp(`${PREFIX}${BLOCK_CONTENT_REGEXP}`);
8
+ /**
9
+ * Blockquote block.
10
+ * - `>` quote character followed by zero or more spaces.
11
+ * - No spaces can appear before the `>` quote character.
12
+ * - Quote block is only broken by `\n\n` two newline characters.
13
+ */
14
+ export const BLOCKQUOTE_RULE = getMarkupRule(BLOCKQUOTE_REGEXP, ([quote], options, key) => ({
15
+ key,
16
+ $$typeof: REACT_ELEMENT_TYPE,
17
+ type: "blockquote",
18
+ props: { children: renderMarkup(quote.replace(INDENT, ""), options, "block") },
19
+ }), ["block", "list"]);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Inline code.
3
+ * - Text surrounded by one or more "`" backtick tilde characters.
4
+ * - Unlike strong/emphasis first or last character of the element can be space, (e.g. `- abc -` will not work).
5
+ * - Closing characters must exactly match opening characters.
6
+ * - Same as Markdown syntax.
7
+ */
8
+ export declare const CODE_RULE: import("../util/rule.js").MarkupRule;
@@ -0,0 +1,18 @@
1
+ import { getRegExp } from "../../util/regexp.js";
2
+ import { REACT_ELEMENT_TYPE } from "../util/internal.js";
3
+ import { BLOCK_CONTENT_REGEXP } from "../util/regexp.js";
4
+ import { getMarkupRule } from "../util/rule.js";
5
+ const CODE_REGEXP = getRegExp(`(?<fence>\`+)(?<code>${BLOCK_CONTENT_REGEXP})\\k<fence>`);
6
+ /**
7
+ * Inline code.
8
+ * - Text surrounded by one or more "`" backtick tilde characters.
9
+ * - Unlike strong/emphasis first or last character of the element can be space, (e.g. `- abc -` will not work).
10
+ * - Closing characters must exactly match opening characters.
11
+ * - Same as Markdown syntax.
12
+ */
13
+ export const CODE_RULE = getMarkupRule(CODE_REGEXP, ({ groups: { code } }, options, key) => ({
14
+ key,
15
+ $$typeof: REACT_ELEMENT_TYPE,
16
+ type: "code",
17
+ props: { children: code },
18
+ }), ["inline", "list"], 10);
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Fenced code blocks
3
+ * - Same as Markdown syntax.
4
+ * - Start when we reach an opening fence on a new line.
5
+ * - Stop when we reach a matching closing fence on a new line, or the end of the string.
6
+ * - Closing fence must be exactly the same as the opening fence, and can be made of three or more "```" backticks, or three or more `~~~` tildes.
7
+ * - If there's no closing fence the code block will run to the end of the current string.
8
+ * - Markdown-style four-space indent syntax is not supported (only fenced code since it's less confusing and more common).
9
+ */
10
+ export declare const FENCED_RULE: import("../util/rule.js").MarkupRule;
@@ -0,0 +1,34 @@
1
+ import { REACT_ELEMENT_TYPE } from "../util/internal.js";
2
+ import { BLOCK_CONTENT_REGEXP, BLOCK_START_REGEXP, LINE_CONTENT_REGEXP, LINE_SPACE_REGEXP, getBlockRegExp } from "../util/regexp.js";
3
+ import { getMarkupRule } from "../util/rule.js";
4
+ const FENCE = "`{3,}|~{3,}";
5
+ const FENCED_REGEXP = getBlockRegExp(`(?<code>${BLOCK_CONTENT_REGEXP})`,
6
+ // Starts with the fence
7
+ `${BLOCK_START_REGEXP}(?<fence>${FENCE}) *(?<title>${LINE_CONTENT_REGEXP})\n`,
8
+ // Ends when we hit the end of the string or the matching closing fence (trims any matching newlines after the fence).
9
+ `(?:${LINE_SPACE_REGEXP}*\n\\k<fence>(?:\\s*\\n)?|$)`);
10
+ /**
11
+ * Fenced code blocks
12
+ * - Same as Markdown syntax.
13
+ * - Start when we reach an opening fence on a new line.
14
+ * - Stop when we reach a matching closing fence on a new line, or the end of the string.
15
+ * - Closing fence must be exactly the same as the opening fence, and can be made of three or more "```" backticks, or three or more `~~~` tildes.
16
+ * - If there's no closing fence the code block will run to the end of the current string.
17
+ * - Markdown-style four-space indent syntax is not supported (only fenced code since it's less confusing and more common).
18
+ */
19
+ export const FENCED_RULE = getMarkupRule(FENCED_REGEXP, ({ groups: { title, code } }, options, key) => ({
20
+ key,
21
+ $$typeof: REACT_ELEMENT_TYPE,
22
+ type: "pre",
23
+ props: {
24
+ children: {
25
+ $$typeof: REACT_ELEMENT_TYPE,
26
+ type: "code",
27
+ key: null,
28
+ props: {
29
+ title: title?.trim() || undefined,
30
+ children: code.trim(),
31
+ },
32
+ },
33
+ },
34
+ }), ["block", "list"], 10);
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Headings are single line only (don't allow multiline).
3
+ * - `#` 1-6 hashes, then one or more spaces, then the title.
4
+ * - `#` must be the first character on the line.
5
+ * - Markdown's underline syntax is not supported (for simplification).
6
+ */
7
+ export declare const HEADING_RULE: import("../util/rule.js").MarkupRule;
@@ -0,0 +1,17 @@
1
+ import { renderMarkup } from "../render.js";
2
+ import { REACT_ELEMENT_TYPE } from "../util/internal.js";
3
+ import { LINE_CONTENT_REGEXP, LINE_SPACE_REGEXP, getLineRegExp } from "../util/regexp.js";
4
+ import { getMarkupRule } from "../util/rule.js";
5
+ const HEADING_REGEXP = getLineRegExp(`(?<prefix>#{1,6})(?:${LINE_SPACE_REGEXP}+(?<heading>${LINE_CONTENT_REGEXP}))?`);
6
+ /**
7
+ * Headings are single line only (don't allow multiline).
8
+ * - `#` 1-6 hashes, then one or more spaces, then the title.
9
+ * - `#` must be the first character on the line.
10
+ * - Markdown's underline syntax is not supported (for simplification).
11
+ */
12
+ export const HEADING_RULE = getMarkupRule(HEADING_REGEXP, ({ groups: { prefix, heading = "" } }, options, key) => ({
13
+ key,
14
+ $$typeof: REACT_ELEMENT_TYPE,
15
+ type: `h${prefix.length}`,
16
+ props: { children: renderMarkup(heading.trim(), options, "inline") },
17
+ }), ["block"]);
@@ -0,0 +1,44 @@
1
+ import type { MarkupRules } from "../util/rule.js";
2
+ /** Markup rules that work in a block context. */
3
+ export declare const MARKUP_RULES_BLOCK: MarkupRules;
4
+ /** Markup rules that work in an inline context. */
5
+ export declare const MARKUP_RULES_INLINE: MarkupRules;
6
+ /**
7
+ * Default markup rules
8
+ *
9
+ * These rules define a syntax similar to Markdown but with improvements:
10
+ * 1. Syntax is more intuitive (e.g. `*strong*` always uses `*` asterisk and `_em_` always uses `_` underscore, and URLs are always autolinked).
11
+ * 2. More compatible with textboxes that wrap lines by default (e.g. single `\n` linebreaks don't need the trailing double space to, they're always treated as `<br />`).
12
+ * 3. Don't support fussy fragile syntax that lets users make mistakes (e.g. literal HTML tags or `&amp;` character entities).
13
+ *
14
+ * @todo Default rules support "list items containing paragraphs" syntax (CommonMark calls this loose lists).
15
+ * - i.e. Lists can include `\n\n` double line breaks, and wrap all their contents in `<p>` entities, i.e. childContext is "block"
16
+ * - Hard because you have to capture the entire list including `\n\n`, so there's no obvious place to end it.
17
+ * - If there are breaks then any sub-lines need to be indented by two or more spaces otherwise it will break the list.
18
+ * - Make reference lists support this loose format too.
19
+ * @todo [ ] Default rules support tables using `|` pipe syntax.
20
+ * @todo [ ] Default rules support todo lists using `- [x]` syntax.
21
+ * @todo [ ] Default rules support new reference syntax (combines reference lists/sidenotes/footnotes/reference and produces <dl> syntax).
22
+ * - All of these can be the same because reference links and Extended Markdown footnotes are basically the same.
23
+ * - e.g. `[Google Maps][1]` → `[1]: http://google.com Content goes here` (Markdown reference link syntax).
24
+ * - e.g. `[Google Maps]` → `[Google Maps]: http://google.com Content goes here` syntax.
25
+ * - e.g. `[DNS]` → `[DNS]: Domain Name System (extended Markdown definition list format).
26
+ * - If a `[Reference]` does not correspond to anything it will not be linked and e.g. will appear unlinked.
27
+ * - Single/double quotes around definition part are optional and are trimmed from the start/end (Extended Markdown definition lists require quotes, but that's dumb).
28
+ * - A `<dl>` definition list is used as the output format for all of these different use cases.
29
+ * - If the first thing in the definition is a URL, then it's recognised as a link reference (and produces an `<a href=""></a>`)
30
+ * - If the first thing in the definition isn't a URL, then it's recognised as a sidenote/footnote and tapping it will scroll you to that point (and popup the definition like Marco Arment's Bigfoot code).
31
+ */
32
+ export declare const MARKUP_RULES: MarkupRules;
33
+ export * from "./blockquote.js";
34
+ export * from "./code.js";
35
+ export * from "./fenced.js";
36
+ export * from "./heading.js";
37
+ export * from "./inline.js";
38
+ export * from "./linebreak.js";
39
+ export * from "./link.js";
40
+ export * from "./link.js";
41
+ export * from "./ordered.js";
42
+ export * from "./paragraph.js";
43
+ export * from "./separator.js";
44
+ export * from "./unordered.js";
@@ -0,0 +1,63 @@
1
+ import { BLOCKQUOTE_RULE } from "./blockquote.js";
2
+ import { CODE_RULE } from "./code.js";
3
+ import { FENCED_RULE } from "./fenced.js";
4
+ import { HEADING_RULE } from "./heading.js";
5
+ import { INLINE_RULE } from "./inline.js";
6
+ import { LINEBREAK_RULE } from "./linebreak.js";
7
+ import { LINK_RULE } from "./link.js";
8
+ import { AUTOLINK_RULE } from "./link.js";
9
+ import { ORDERED_RULE } from "./ordered.js";
10
+ import { PARAGRAPH_RULE } from "./paragraph.js";
11
+ import { SEPARATOR_RULE } from "./separator.js";
12
+ import { UNORDERED_RULE } from "./unordered.js";
13
+ /** Markup rules that work in a block context. */
14
+ export const MARKUP_RULES_BLOCK = [
15
+ FENCED_RULE,
16
+ HEADING_RULE,
17
+ SEPARATOR_RULE,
18
+ UNORDERED_RULE,
19
+ ORDERED_RULE,
20
+ BLOCKQUOTE_RULE,
21
+ PARAGRAPH_RULE,
22
+ ];
23
+ /** Markup rules that work in an inline context. */
24
+ export const MARKUP_RULES_INLINE = [CODE_RULE, LINK_RULE, AUTOLINK_RULE, INLINE_RULE, LINEBREAK_RULE];
25
+ /**
26
+ * Default markup rules
27
+ *
28
+ * These rules define a syntax similar to Markdown but with improvements:
29
+ * 1. Syntax is more intuitive (e.g. `*strong*` always uses `*` asterisk and `_em_` always uses `_` underscore, and URLs are always autolinked).
30
+ * 2. More compatible with textboxes that wrap lines by default (e.g. single `\n` linebreaks don't need the trailing double space to, they're always treated as `<br />`).
31
+ * 3. Don't support fussy fragile syntax that lets users make mistakes (e.g. literal HTML tags or `&amp;` character entities).
32
+ *
33
+ * @todo Default rules support "list items containing paragraphs" syntax (CommonMark calls this loose lists).
34
+ * - i.e. Lists can include `\n\n` double line breaks, and wrap all their contents in `<p>` entities, i.e. childContext is "block"
35
+ * - Hard because you have to capture the entire list including `\n\n`, so there's no obvious place to end it.
36
+ * - If there are breaks then any sub-lines need to be indented by two or more spaces otherwise it will break the list.
37
+ * - Make reference lists support this loose format too.
38
+ * @todo [ ] Default rules support tables using `|` pipe syntax.
39
+ * @todo [ ] Default rules support todo lists using `- [x]` syntax.
40
+ * @todo [ ] Default rules support new reference syntax (combines reference lists/sidenotes/footnotes/reference and produces <dl> syntax).
41
+ * - All of these can be the same because reference links and Extended Markdown footnotes are basically the same.
42
+ * - e.g. `[Google Maps][1]` → `[1]: http://google.com Content goes here` (Markdown reference link syntax).
43
+ * - e.g. `[Google Maps]` → `[Google Maps]: http://google.com Content goes here` syntax.
44
+ * - e.g. `[DNS]` → `[DNS]: Domain Name System (extended Markdown definition list format).
45
+ * - If a `[Reference]` does not correspond to anything it will not be linked and e.g. will appear unlinked.
46
+ * - Single/double quotes around definition part are optional and are trimmed from the start/end (Extended Markdown definition lists require quotes, but that's dumb).
47
+ * - A `<dl>` definition list is used as the output format for all of these different use cases.
48
+ * - If the first thing in the definition is a URL, then it's recognised as a link reference (and produces an `<a href=""></a>`)
49
+ * - If the first thing in the definition isn't a URL, then it's recognised as a sidenote/footnote and tapping it will scroll you to that point (and popup the definition like Marco Arment's Bigfoot code).
50
+ */
51
+ export const MARKUP_RULES = [...MARKUP_RULES_BLOCK, ...MARKUP_RULES_INLINE];
52
+ export * from "./blockquote.js";
53
+ export * from "./code.js";
54
+ export * from "./fenced.js";
55
+ export * from "./heading.js";
56
+ export * from "./inline.js";
57
+ export * from "./linebreak.js";
58
+ export * from "./link.js";
59
+ export * from "./link.js";
60
+ export * from "./ordered.js";
61
+ export * from "./paragraph.js";
62
+ export * from "./separator.js";
63
+ export * from "./unordered.js";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Inline strong, emphasis, insert, delete, highlight.
3
+ * - Inline strong text wrapped in one or more `*` asterisks.
4
+ * - Inline emphasis text wrapped in one or more `_` underscores.
5
+ * - Inline inserted text wrapped in one or more `+` pluses.
6
+ * - Inline deleted text wrapped in one or more `-` minuses or `~` tildes.
7
+ * - Inline highlighted text wrapped in one or more `=` equals or `:` colons.
8
+ * - Whitespace cannot be the first or last character of the element (e.g. `* abc *` will not work).
9
+ * - Closing chars must match opening characters.
10
+ * - Cannot occur in the middle of a word (e.g. `this*that*this` will not work).
11
+ * - Closing characters must exactly match opening characters.
12
+ * - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
13
+ */
14
+ export declare const INLINE_RULE: import("../util/rule.js").MarkupRule;
@@ -0,0 +1,26 @@
1
+ import { renderMarkup } from "../render.js";
2
+ import { REACT_ELEMENT_TYPE } from "../util/internal.js";
3
+ import { getWordRegExp } from "../util/regexp.js";
4
+ import { getMarkupRule } from "../util/rule.js";
5
+ /** Map characters, e.g. `*`, to their coresponding HTML tag, e.g. `strong` */
6
+ 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.
7
+ const INLINE_REGEXP = getWordRegExp(`(?<wrap>(?<char>[${Object.keys(INLINE_CHARS).join("")}])+)(?<text>(?!\\k<char>)\\S(?:[\\s\\S]*?(?!\\k<char>)\\S)?)\\k<wrap>`);
8
+ /**
9
+ * Inline strong, emphasis, insert, delete, highlight.
10
+ * - Inline strong text wrapped in one or more `*` asterisks.
11
+ * - Inline emphasis text wrapped in one or more `_` underscores.
12
+ * - Inline inserted text wrapped in one or more `+` pluses.
13
+ * - Inline deleted text wrapped in one or more `-` minuses or `~` tildes.
14
+ * - Inline highlighted text wrapped in one or more `=` equals or `:` colons.
15
+ * - Whitespace cannot be the first or last character of the element (e.g. `* abc *` will not work).
16
+ * - Closing chars must match opening characters.
17
+ * - Cannot occur in the middle of a word (e.g. `this*that*this` will not work).
18
+ * - Closing characters must exactly match opening characters.
19
+ * - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
20
+ */
21
+ export const INLINE_RULE = getMarkupRule(INLINE_REGEXP, ({ groups: { char, text } }, options, key) => ({
22
+ key,
23
+ $$typeof: REACT_ELEMENT_TYPE,
24
+ type: INLINE_CHARS[char],
25
+ props: { children: renderMarkup(text, options, "inline") },
26
+ }), ["inline", "list", "link"]);