shelving 1.219.1 → 1.221.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/extract/MarkdownExtractor.js +2 -3
- package/markup/MarkupParser.d.ts +97 -0
- package/markup/MarkupParser.js +249 -0
- package/markup/MarkupRule.d.ts +19 -0
- package/markup/{util/rule.js → MarkupRule.js} +0 -1
- package/markup/Parser.d.ts +3 -0
- package/markup/Parser.js +2 -0
- package/markup/index.d.ts +3 -4
- package/markup/index.js +3 -5
- package/markup/rule/blockquote.d.ts +1 -2
- package/markup/rule/blockquote.js +2 -4
- package/markup/rule/code.d.ts +2 -1
- package/markup/rule/code.js +5 -3
- package/markup/rule/fenced.d.ts +1 -1
- package/markup/rule/fenced.js +3 -7
- package/markup/rule/heading.d.ts +1 -1
- package/markup/rule/heading.js +3 -5
- package/markup/rule/index.d.ts +1 -21
- package/markup/rule/index.js +11 -21
- package/markup/rule/inline.d.ts +1 -1
- package/markup/rule/inline.js +3 -5
- package/markup/rule/linebreak.d.ts +1 -1
- package/markup/rule/linebreak.js +4 -6
- package/markup/rule/link.d.ts +5 -12
- package/markup/rule/link.js +11 -17
- package/markup/rule/ordered.d.ts +1 -4
- package/markup/rule/ordered.js +8 -10
- package/markup/rule/paragraph.d.ts +1 -4
- package/markup/rule/paragraph.js +2 -6
- package/markup/rule/separator.d.ts +1 -1
- package/markup/rule/separator.js +4 -3
- package/markup/rule/table.d.ts +1 -5
- package/markup/rule/table.js +4 -11
- package/markup/rule/unordered.d.ts +3 -6
- package/markup/rule/unordered.js +8 -11
- package/markup/util/regexp.d.ts +1 -1
- package/package.json +1 -1
- package/ui/app/App.d.ts +3 -3
- package/ui/app/App.tsx +3 -4
- package/ui/block/Address.d.ts +3 -3
- package/ui/block/Address.tsx +3 -4
- package/ui/block/Block.d.ts +3 -3
- package/ui/block/Block.tsx +3 -4
- package/ui/block/Blockquote.d.ts +3 -3
- package/ui/block/Blockquote.tsx +3 -4
- package/ui/block/Card.d.ts +1 -2
- package/ui/block/Card.tsx +1 -3
- package/ui/block/Definitions.d.ts +3 -5
- package/ui/block/Definitions.tsx +3 -5
- package/ui/block/Figure.d.ts +2 -2
- package/ui/block/Figure.tsx +2 -2
- package/ui/block/Flex.d.ts +3 -3
- package/ui/block/Flex.tsx +3 -4
- package/ui/block/Heading.d.ts +3 -4
- package/ui/block/Heading.tsx +3 -4
- package/ui/block/Paragraph.d.ts +3 -3
- package/ui/block/Paragraph.tsx +3 -3
- package/ui/block/Preformatted.d.ts +3 -3
- package/ui/block/Preformatted.tsx +3 -3
- package/ui/block/Prose.d.ts +3 -3
- package/ui/block/Prose.tsx +3 -4
- package/ui/block/Section.d.ts +3 -3
- package/ui/block/Section.tsx +3 -3
- package/ui/block/Table.d.ts +2 -3
- package/ui/block/Table.tsx +2 -4
- package/ui/block/Video.d.ts +5 -7
- package/ui/block/Video.tsx +5 -8
- package/ui/dialog/Dialog.d.ts +4 -5
- package/ui/dialog/Dialog.tsx +4 -6
- package/ui/dialog/Dialogs.d.ts +2 -2
- package/ui/dialog/Dialogs.tsx +2 -3
- package/ui/dialog/Modal.d.ts +4 -4
- package/ui/dialog/Modal.tsx +3 -4
- package/ui/form/CheckboxInput.d.ts +3 -3
- package/ui/form/CheckboxInput.tsx +3 -4
- package/ui/form/Clickable.d.ts +2 -3
- package/ui/form/Clickable.tsx +2 -3
- package/ui/form/Field.d.ts +2 -2
- package/ui/form/Field.tsx +2 -2
- package/ui/form/Form.d.ts +2 -7
- package/ui/form/Form.tsx +2 -7
- package/ui/form/FormFooter.d.ts +2 -2
- package/ui/form/FormFooter.tsx +2 -2
- package/ui/form/Input.d.ts +3 -4
- package/ui/form/Input.tsx +3 -2
- package/ui/form/OutputInput.d.ts +3 -3
- package/ui/form/OutputInput.tsx +3 -4
- package/ui/form/RadioInput.d.ts +3 -3
- package/ui/form/RadioInput.tsx +3 -4
- package/ui/form/SchemaInput.d.ts +3 -3
- package/ui/form/SchemaInput.tsx +3 -4
- package/ui/form/SubmitButton.d.ts +3 -3
- package/ui/form/SubmitButton.tsx +3 -4
- package/ui/inline/Code.d.ts +6 -9
- package/ui/inline/Code.tsx +6 -13
- package/ui/inline/Deleted.d.ts +3 -3
- package/ui/inline/Deleted.tsx +3 -4
- package/ui/inline/Emphasis.d.ts +3 -3
- package/ui/inline/Emphasis.tsx +3 -4
- package/ui/inline/Inserted.d.ts +3 -3
- package/ui/inline/Inserted.tsx +3 -4
- package/ui/inline/Mark.d.ts +3 -3
- package/ui/inline/Mark.tsx +3 -4
- package/ui/inline/Small.d.ts +3 -3
- package/ui/inline/Small.tsx +3 -4
- package/ui/inline/Strong.d.ts +3 -3
- package/ui/inline/Strong.tsx +3 -4
- package/ui/inline/Subscript.d.ts +3 -3
- package/ui/inline/Subscript.tsx +3 -4
- package/ui/inline/Superscript.d.ts +3 -3
- package/ui/inline/Superscript.tsx +3 -4
- package/ui/inline/When.d.ts +3 -3
- package/ui/inline/When.tsx +3 -3
- package/ui/layout/CenteredLayout.d.ts +3 -3
- package/ui/layout/CenteredLayout.tsx +3 -3
- package/ui/layout/SidebarLayout.d.ts +2 -3
- package/ui/layout/SidebarLayout.tsx +2 -3
- package/ui/menu/Menu.d.ts +2 -2
- package/ui/menu/Menu.tsx +2 -3
- package/ui/misc/Catcher.d.ts +5 -8
- package/ui/misc/Catcher.js +0 -1
- package/ui/misc/Catcher.tsx +5 -11
- package/ui/misc/Mapper.d.ts +3 -3
- package/ui/misc/Mapper.tsx +2 -2
- package/ui/misc/Markup.d.ts +2 -2
- package/ui/misc/Markup.js +5 -6
- package/ui/misc/Markup.tsx +7 -7
- package/ui/misc/MetaContext.d.ts +2 -3
- package/ui/misc/MetaContext.tsx +3 -4
- package/ui/misc/Tag.d.ts +1 -2
- package/ui/misc/Tag.tsx +2 -4
- package/ui/notice/Message.d.ts +0 -2
- package/ui/notice/Message.tsx +0 -2
- package/ui/notice/Notice.d.ts +3 -4
- package/ui/notice/Notice.tsx +3 -4
- package/ui/page/HTML.d.ts +3 -3
- package/ui/page/HTML.tsx +3 -4
- package/ui/page/Page.d.ts +3 -3
- package/ui/page/Page.tsx +3 -4
- package/ui/router/Navigation.d.ts +4 -5
- package/ui/router/Navigation.tsx +4 -7
- package/ui/transition/Transition.d.ts +3 -3
- package/ui/transition/Transition.tsx +3 -3
- package/ui/tree/TreeApp.d.ts +3 -4
- package/ui/tree/TreeApp.tsx +3 -4
- package/ui/util/README.md +13 -0
- package/ui/util/index.d.ts +1 -0
- package/ui/util/index.js +1 -0
- package/ui/util/index.ts +1 -0
- package/ui/util/props.d.ts +9 -0
- package/ui/util/props.ts +11 -0
- package/util/link.d.ts +5 -5
- package/markup/render.d.ts +0 -13
- package/markup/render.js +0 -63
- package/markup/util/internal.d.ts +0 -2
- package/markup/util/internal.js +0 -2
- package/markup/util/options.d.ts +0 -29
- package/markup/util/rule.d.ts +0 -17
- /package/{markup/util/options.js → ui/util/props.js} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { MARKUP_OPTIONS } from "../markup/rule/index.js";
|
|
1
|
+
import { MARKUP_PARSER } from "../markup/MarkupParser.js";
|
|
3
2
|
import { getElementText } from "../util/element.js";
|
|
4
3
|
import { FileExtractor } from "./FileExtractor.js";
|
|
5
4
|
/**
|
|
@@ -53,7 +52,7 @@ export function extractMarkdownDescription(text) {
|
|
|
53
52
|
if (!paragraph.length)
|
|
54
53
|
return;
|
|
55
54
|
// Render the paragraph as markup then strip every tag, so inline syntax resolves to clean plain text.
|
|
56
|
-
const rendered =
|
|
55
|
+
const rendered = MARKUP_PARSER.parse(paragraph.join(" "));
|
|
57
56
|
const summary = getElementText(rendered).replace(/\s+/g, " ").trim();
|
|
58
57
|
return summary || undefined;
|
|
59
58
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ImmutableArray } from "../util/array.js";
|
|
3
|
+
import { type PossibleLink } from "../util/link.js";
|
|
4
|
+
import type { Nullish } from "../util/null.js";
|
|
5
|
+
import { type ImmutableURI, type URISchemes } from "../util/uri.js";
|
|
6
|
+
import type { ImmutableURL } from "../util/url.js";
|
|
7
|
+
import type { MarkupRule, MarkupRules } from "./MarkupRule.js";
|
|
8
|
+
import type { Parser } from "./Parser.js";
|
|
9
|
+
/** The current parsing options (represents the current state of the parsing). */
|
|
10
|
+
export type MarkupOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* The active list of parsing rules.
|
|
13
|
+
* @default MARKUP_RULES The default list of markup rules.
|
|
14
|
+
*/
|
|
15
|
+
readonly rules?: MarkupRules | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Set the `rel=""` property used for any links (e.g. `rel="nofollow ugc"`).
|
|
18
|
+
* @example "nofollow ugc" // Stop user-generated content ruining our SEO juice.
|
|
19
|
+
*/
|
|
20
|
+
readonly rel?: string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Current page URL — used as the base for resolving relative refs (`./foo`, `#x`, bare segments) in link hrefs.
|
|
23
|
+
*/
|
|
24
|
+
readonly url?: ImmutableURL | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Site root URL — used as the base for resolving site-absolute path hrefs (`/foo`), honoring its subfolder.
|
|
27
|
+
*/
|
|
28
|
+
readonly root?: ImmutableURL | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Valid URI schemes/protocols for URLs and URIs.
|
|
31
|
+
* @example ["http:", "https:"]
|
|
32
|
+
* @default ["http:", "https:"]
|
|
33
|
+
*/
|
|
34
|
+
readonly schemes?: URISchemes | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Default context to use if one isn't set. Defaults to `"block"`
|
|
37
|
+
*/
|
|
38
|
+
readonly context?: string;
|
|
39
|
+
};
|
|
40
|
+
export declare class MarkupParser implements Parser<string, ReactNode> {
|
|
41
|
+
/**
|
|
42
|
+
* The list of parsing rules this parser applies.
|
|
43
|
+
*/
|
|
44
|
+
readonly rules: MarkupRules;
|
|
45
|
+
/**
|
|
46
|
+
* Calculated list of priorities to iterate over (extracted from the rules), e.g. [10, 0, -10]
|
|
47
|
+
*/
|
|
48
|
+
readonly priorities: ImmutableArray<number>;
|
|
49
|
+
/**
|
|
50
|
+
* Set the `rel=""` property used for any links (e.g. `rel="nofollow ugc"`).
|
|
51
|
+
* @example "nofollow ugc"
|
|
52
|
+
*/
|
|
53
|
+
readonly rel: string | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Current page URL — used as the base for resolving relative refs (`./foo`, `#x`, bare segments) in link hrefs.
|
|
56
|
+
* @default Falls back to `root` if not set.
|
|
57
|
+
*/
|
|
58
|
+
readonly url: ImmutableURL | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Site root URL — used as the base for resolving site-absolute path hrefs (`/foo`), honoring its subfolder.
|
|
61
|
+
* @default Falls back to `url` if not set.
|
|
62
|
+
*/
|
|
63
|
+
readonly root: ImmutableURL | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Valid URI schemes/protocols for URLs and URIs.
|
|
66
|
+
* @example ["http:", "https:"]
|
|
67
|
+
* @default ["http:", "https:"]
|
|
68
|
+
*/
|
|
69
|
+
readonly schemes: URISchemes;
|
|
70
|
+
/**
|
|
71
|
+
* Default context to use if one isn't set. Defaults to `"block"`
|
|
72
|
+
*/
|
|
73
|
+
readonly context: string;
|
|
74
|
+
constructor({ rules, rel, url, root, schemes, context }?: MarkupOptions);
|
|
75
|
+
/**
|
|
76
|
+
* Parse a text string as Markdownish markup syntax and render it as elements.
|
|
77
|
+
* - Syntax is not defined by this code, but by the rules supplied to it.
|
|
78
|
+
*
|
|
79
|
+
* @param input The string content possibly containing markup syntax, e.g. "This is a *bold* string.
|
|
80
|
+
* @param parser A markup parser instance.
|
|
81
|
+
* @param context The context to render in (defaults to `"block"`).
|
|
82
|
+
*
|
|
83
|
+
* @returns A React node — an element, a string, `null`, or an array of zero or more of those.
|
|
84
|
+
*/
|
|
85
|
+
parse(input: string, context?: string): ReactNode;
|
|
86
|
+
/** Yield the rules active in `context` that sit in the given priority tier. */
|
|
87
|
+
getRules(context: string, priority: number): Iterable<MarkupRule>;
|
|
88
|
+
/**
|
|
89
|
+
* Get a HREF link with the correct context of our `options.url` and `options.root`
|
|
90
|
+
*
|
|
91
|
+
* @returns `ImmutableURI` a (URL) object if the link matches and is parseable and has an allowed scheme.
|
|
92
|
+
* @returns `undefined` if the link does not amtch the allowed `options.schemes`
|
|
93
|
+
*/
|
|
94
|
+
getLink(href: Nullish<PossibleLink>): ImmutableURI | undefined;
|
|
95
|
+
}
|
|
96
|
+
/** MarkupParser sentinel with the default markup rules */
|
|
97
|
+
export declare const MARKUP_PARSER: MarkupParser;
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { getLink } from "../util/link.js";
|
|
2
|
+
import { HTTP_SCHEMES } from "../util/uri.js";
|
|
3
|
+
import { MARKUP_RULES } from "./rule/index.js";
|
|
4
|
+
export class MarkupParser {
|
|
5
|
+
/**
|
|
6
|
+
* The list of parsing rules this parser applies.
|
|
7
|
+
*/
|
|
8
|
+
rules;
|
|
9
|
+
/**
|
|
10
|
+
* Calculated list of priorities to iterate over (extracted from the rules), e.g. [10, 0, -10]
|
|
11
|
+
*/
|
|
12
|
+
priorities;
|
|
13
|
+
/**
|
|
14
|
+
* Set the `rel=""` property used for any links (e.g. `rel="nofollow ugc"`).
|
|
15
|
+
* @example "nofollow ugc"
|
|
16
|
+
*/
|
|
17
|
+
rel;
|
|
18
|
+
/**
|
|
19
|
+
* Current page URL — used as the base for resolving relative refs (`./foo`, `#x`, bare segments) in link hrefs.
|
|
20
|
+
* @default Falls back to `root` if not set.
|
|
21
|
+
*/
|
|
22
|
+
url;
|
|
23
|
+
/**
|
|
24
|
+
* Site root URL — used as the base for resolving site-absolute path hrefs (`/foo`), honoring its subfolder.
|
|
25
|
+
* @default Falls back to `url` if not set.
|
|
26
|
+
*/
|
|
27
|
+
root;
|
|
28
|
+
/**
|
|
29
|
+
* Valid URI schemes/protocols for URLs and URIs.
|
|
30
|
+
* @example ["http:", "https:"]
|
|
31
|
+
* @default ["http:", "https:"]
|
|
32
|
+
*/
|
|
33
|
+
schemes;
|
|
34
|
+
/**
|
|
35
|
+
* Default context to use if one isn't set. Defaults to `"block"`
|
|
36
|
+
*/
|
|
37
|
+
context;
|
|
38
|
+
constructor({ rules = MARKUP_RULES, rel, url, root, schemes = HTTP_SCHEMES, context = "block" } = {}) {
|
|
39
|
+
this.rules = rules;
|
|
40
|
+
this.priorities = _getPriorities(rules);
|
|
41
|
+
this.rel = rel;
|
|
42
|
+
this.url = url;
|
|
43
|
+
this.root = root;
|
|
44
|
+
this.schemes = schemes;
|
|
45
|
+
this.context = context;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse a text string as Markdownish markup syntax and render it as elements.
|
|
49
|
+
* - Syntax is not defined by this code, but by the rules supplied to it.
|
|
50
|
+
*
|
|
51
|
+
* @param input The string content possibly containing markup syntax, e.g. "This is a *bold* string.
|
|
52
|
+
* @param parser A markup parser instance.
|
|
53
|
+
* @param context The context to render in (defaults to `"block"`).
|
|
54
|
+
*
|
|
55
|
+
* @returns A React node — an element, a string, `null`, or an array of zero or more of those.
|
|
56
|
+
*/
|
|
57
|
+
parse(input, context = "block") {
|
|
58
|
+
const nodes = _parseNodes(input, this, context);
|
|
59
|
+
return !nodes.length ? null : nodes.length === 1 ? nodes[0] : nodes;
|
|
60
|
+
}
|
|
61
|
+
/** Yield the rules active in `context` that sit in the given priority tier. */
|
|
62
|
+
*getRules(context, priority) {
|
|
63
|
+
for (const r of this.rules)
|
|
64
|
+
if (r.priority === priority && r.contexts.includes(context))
|
|
65
|
+
yield r;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get a HREF link with the correct context of our `options.url` and `options.root`
|
|
69
|
+
*
|
|
70
|
+
* @returns `ImmutableURI` a (URL) object if the link matches and is parseable and has an allowed scheme.
|
|
71
|
+
* @returns `undefined` if the link does not amtch the allowed `options.schemes`
|
|
72
|
+
*/
|
|
73
|
+
getLink(href) {
|
|
74
|
+
const link = getLink(href, this.url, this.root);
|
|
75
|
+
if (link && this.schemes.includes(link.protocol))
|
|
76
|
+
return link;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Extract the unique rule priorities, ordered highest first — these are the tiers to resolve in turn. */
|
|
80
|
+
function _getPriorities(rules) {
|
|
81
|
+
const priorities = [];
|
|
82
|
+
for (const { priority } of rules)
|
|
83
|
+
if (!priorities.includes(priority))
|
|
84
|
+
priorities.push(priority);
|
|
85
|
+
return priorities.sort().reverse();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Parse a string into its rendered nodes using a tiered / masking engine.
|
|
89
|
+
*
|
|
90
|
+
* Rules are grouped into priority tiers and resolved highest tier first. Once a tier claims a
|
|
91
|
+
* region it is "masked" (blanked in a working copy of the string) so lower-priority rules cannot
|
|
92
|
+
* match into — or across — it, but can still match around it. That single mechanism is the fix
|
|
93
|
+
* for code spans that straddle link delimiters: a code span is masked before links resolve, so a
|
|
94
|
+
* link either wraps a whole masked code span (and re-parses it) or cannot form at all.
|
|
95
|
+
*
|
|
96
|
+
* Rules own the recursion into their own children — they call `parser.parse` again, optionally
|
|
97
|
+
* with a different context — so the engine never reaches inside a rule's content itself.
|
|
98
|
+
*/
|
|
99
|
+
function _parseNodes(input, parser, context) {
|
|
100
|
+
// Resolve tier by tier. `claimed` collects the winning regions; `masked` hides each resolved
|
|
101
|
+
// region from every lower tier.
|
|
102
|
+
const claimed = [];
|
|
103
|
+
let masked = input;
|
|
104
|
+
for (const priority of parser.priorities) {
|
|
105
|
+
const higher = Array.from(claimed); // Snapshot — claims from already-resolved (higher) tiers.
|
|
106
|
+
for (const claim of _scanTier(masked, input, parser, context, priority, higher)) {
|
|
107
|
+
// A claim that wraps earlier (higher-tier) claims absorbs them: the wrapper re-parses
|
|
108
|
+
// that text itself (e.g. a link re-parsing its own title).
|
|
109
|
+
for (let i = claimed.length - 1; i >= 0; i--) {
|
|
110
|
+
const c = claimed[i];
|
|
111
|
+
if (c && c.start >= claim.start && c.end <= claim.end)
|
|
112
|
+
claimed.splice(i, 1);
|
|
113
|
+
}
|
|
114
|
+
claimed.push(claim);
|
|
115
|
+
masked = _mask(masked, claim.start, claim.end);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Walk left to right: raw text fills the gaps, rendered elements fill the claims. Each claim
|
|
119
|
+
// already carries the capture groups recovered against the original text, so no rule's regexp
|
|
120
|
+
// needs to run a second time here.
|
|
121
|
+
claimed.sort((a, b) => a.start - b.start);
|
|
122
|
+
const nodes = [];
|
|
123
|
+
let pos = 0;
|
|
124
|
+
for (const { rule, start, end, groups } of claimed) {
|
|
125
|
+
if (start > pos)
|
|
126
|
+
nodes.push(input.slice(pos, start));
|
|
127
|
+
nodes.push(rule.render(start.toString(), groups, parser));
|
|
128
|
+
pos = end;
|
|
129
|
+
}
|
|
130
|
+
if (pos < input.length)
|
|
131
|
+
nodes.push(input.slice(pos));
|
|
132
|
+
return nodes;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Yield one tier's winning claims, left to right, non-overlapping.
|
|
136
|
+
*
|
|
137
|
+
* "Leftmost wins" needs every rule's next match up front — but instead of throwing the losers
|
|
138
|
+
* away we cache one match per rule, and only recompute a rule's match when the chosen claim
|
|
139
|
+
* actually invalidated it. A rule whose match still lies ahead is reused untouched.
|
|
140
|
+
*/
|
|
141
|
+
function* _scanTier(masked, input, parser, context, priority, higher) {
|
|
142
|
+
// Materialise this tier's rules.
|
|
143
|
+
const rules = Array.from(parser.getRules(context, priority));
|
|
144
|
+
// Prime one cached match per rule.
|
|
145
|
+
const cache = [];
|
|
146
|
+
for (const rule of rules)
|
|
147
|
+
cache.push(_findFrom(rule, masked, input, 0, higher));
|
|
148
|
+
for (;;) {
|
|
149
|
+
// The leftmost cached match wins; on a tie the earlier rule in the list wins.
|
|
150
|
+
let best;
|
|
151
|
+
for (const claim of cache)
|
|
152
|
+
if (claim && (!best || claim.start < best.start))
|
|
153
|
+
best = claim;
|
|
154
|
+
if (!best)
|
|
155
|
+
return;
|
|
156
|
+
yield best;
|
|
157
|
+
// Keep every cached match still ahead of `best`; recompute only the rules whose match overlapped (or was) `best`.
|
|
158
|
+
for (let i = 0; i < rules.length; i++) {
|
|
159
|
+
const rule = rules[i];
|
|
160
|
+
const claim = cache[i];
|
|
161
|
+
if (rule && (!claim || claim.start < best.end))
|
|
162
|
+
cache[i] = _findFrom(rule, masked, input, best.end, higher);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Find the first valid claim for `rule` in `masked` at or after `from`, or `undefined`.
|
|
168
|
+
* - A claim is valid if it sits in free space, or if it genuinely wraps the higher-tier claims it spans.
|
|
169
|
+
* - Confirmed by re-running the rule on the original (unmasked) slice and checking it still matches the whole region.
|
|
170
|
+
* - A match that merely straddles a masked region (e.g. a paragraph's trailing whitespace swallowing a fenced block) is spurious and is retried bounded by the claim it crossed.
|
|
171
|
+
*/
|
|
172
|
+
function _findFrom(rule, masked, input, from, higher) {
|
|
173
|
+
let lo = from;
|
|
174
|
+
for (;;) {
|
|
175
|
+
// Advance `lo` past any higher-tier claim that covers it.
|
|
176
|
+
for (let moved = true; moved;) {
|
|
177
|
+
moved = false;
|
|
178
|
+
for (const h of higher)
|
|
179
|
+
if (h.start <= lo && lo < h.end) {
|
|
180
|
+
lo = h.end;
|
|
181
|
+
moved = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (lo >= masked.length)
|
|
185
|
+
return undefined;
|
|
186
|
+
const match = rule.regexp.exec(masked.slice(lo));
|
|
187
|
+
if (!match)
|
|
188
|
+
return undefined;
|
|
189
|
+
const start = lo + match.index;
|
|
190
|
+
const end = start + match[0].length;
|
|
191
|
+
// Inspect the higher-tier claims this match touches in a single allocation-free pass:
|
|
192
|
+
// - `leadingEnd` — a claim starts at/before the match, so the match cannot begin here.
|
|
193
|
+
// - `interior` — every spanned claim sits strictly inside (a possible genuine wrapper).
|
|
194
|
+
// - `wallStart`/`wallEnd` — the first claim the match crosses, used to bound a retry.
|
|
195
|
+
let overlaps = false;
|
|
196
|
+
let leadingEnd = -1;
|
|
197
|
+
let interior = true;
|
|
198
|
+
let wallStart = masked.length;
|
|
199
|
+
let wallEnd = -1;
|
|
200
|
+
for (const h of higher) {
|
|
201
|
+
if (h.start < end && h.end > start) {
|
|
202
|
+
overlaps = true;
|
|
203
|
+
if (h.start <= start) {
|
|
204
|
+
if (h.end > leadingEnd)
|
|
205
|
+
leadingEnd = h.end;
|
|
206
|
+
}
|
|
207
|
+
else if (h.end >= end) {
|
|
208
|
+
interior = false;
|
|
209
|
+
}
|
|
210
|
+
if (h.start < wallStart) {
|
|
211
|
+
wallStart = h.start;
|
|
212
|
+
wallEnd = h.end;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (!overlaps)
|
|
217
|
+
return { rule, start, end, groups: match.groups };
|
|
218
|
+
// A higher claim starts at or before this match — it cannot begin here, skip past it.
|
|
219
|
+
if (leadingEnd >= 0) {
|
|
220
|
+
lo = leadingEnd;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
// A genuine wrapper holds every spanned claim strictly inside it (delimiters of its own on
|
|
224
|
+
// both sides) and still matches the whole region when re-run on the original (unmasked)
|
|
225
|
+
// slice. A claim that merely shares a boundary — a paragraph whose trailing whitespace
|
|
226
|
+
// swallows the block below it — is spurious, not a wrapper.
|
|
227
|
+
if (interior) {
|
|
228
|
+
const original = rule.regexp.exec(input.slice(start, end));
|
|
229
|
+
if (original && !original.index && original[0].length === end - start)
|
|
230
|
+
return { rule, start, end, groups: original.groups };
|
|
231
|
+
}
|
|
232
|
+
// Spurious span — retry bounded by the first claim it crossed.
|
|
233
|
+
const bounded = rule.regexp.exec(masked.slice(lo, wallStart));
|
|
234
|
+
if (bounded) {
|
|
235
|
+
const s = lo + bounded.index;
|
|
236
|
+
return { rule, start: s, end: s + bounded[0].length, groups: bounded.groups };
|
|
237
|
+
}
|
|
238
|
+
lo = wallEnd;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/** Blank the `[start, end)` region of `text` — every character becomes a space, except newlines. */
|
|
242
|
+
function _mask(text, start, end) {
|
|
243
|
+
let blanked = "";
|
|
244
|
+
for (let i = start; i < end; i++)
|
|
245
|
+
blanked += text[i] === "\n" ? "\n" : " ";
|
|
246
|
+
return `${text.slice(0, start)}${blanked}${text.slice(end)}`;
|
|
247
|
+
}
|
|
248
|
+
/** MarkupParser sentinel with the default markup rules */
|
|
249
|
+
export const MARKUP_PARSER = new MarkupParser();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
import type { EmptyDictionary } from "../util/dictionary.js";
|
|
3
|
+
import type { NamedRegExp, NamedRegExpData } from "../util/regexp.js";
|
|
4
|
+
import type { MarkupParser } from "./MarkupParser.js";
|
|
5
|
+
export type MarkupContexts = [string, ...string[]];
|
|
6
|
+
export interface MarkupRule {
|
|
7
|
+
/** Regular expression used for matching the rule. */
|
|
8
|
+
regexp: RegExp;
|
|
9
|
+
/** Use the matched data to render an element. */
|
|
10
|
+
render(key: string, data: NamedRegExpData | undefined, parser: MarkupParser): ReactElement;
|
|
11
|
+
/** One or more contexts this rule should render in. */
|
|
12
|
+
contexts: MarkupContexts;
|
|
13
|
+
/** Priority for this rule (higher priority rules override lower priority rules). */
|
|
14
|
+
priority: number;
|
|
15
|
+
}
|
|
16
|
+
export type MarkupRules = readonly MarkupRule[];
|
|
17
|
+
/** Helper to make it easier to create typed `MarkupRule` instances using `NamedRegExp` regular expressions. */
|
|
18
|
+
export declare function createMarkupRule<T extends NamedRegExpData>(regexp: NamedRegExp<T>, render: (key: string, data: T, parser: MarkupParser) => ReactElement, contexts: MarkupContexts, priority?: number): MarkupRule;
|
|
19
|
+
export declare function createMarkupRule(regexp: RegExp, render: (key: string, data: EmptyDictionary, parser: MarkupParser) => ReactElement, contexts: MarkupContexts, priority?: number): MarkupRule;
|
package/markup/Parser.js
ADDED
package/markup/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./util/rule.js";
|
|
4
|
-
export * from "./render.js";
|
|
1
|
+
export * from "./MarkupParser.js";
|
|
2
|
+
export * from "./MarkupRule.js";
|
|
5
3
|
export * from "./rule/index.js";
|
|
4
|
+
export * from "./util/regexp.js";
|
package/markup/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./util/rule.js";
|
|
4
|
-
// export * from "./util/internal.js"; // Not exported.
|
|
5
|
-
export * from "./render.js";
|
|
1
|
+
export * from "./MarkupParser.js";
|
|
2
|
+
export * from "./MarkupRule.js";
|
|
6
3
|
export * from "./rule/index.js";
|
|
4
|
+
export * from "./util/regexp.js";
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export declare const BLOCKQUOTE_REGEXP: RegExp;
|
|
2
1
|
/**
|
|
3
2
|
* Blockquote block.
|
|
4
3
|
* - `>` quote character followed by zero or more spaces.
|
|
5
4
|
* - No spaces can appear before the `>` quote character.
|
|
6
5
|
* - Quote block is only broken by `\n\n` two newline characters.
|
|
7
6
|
*/
|
|
8
|
-
export declare const BLOCKQUOTE_RULE: import("../
|
|
7
|
+
export declare const BLOCKQUOTE_RULE: import("../MarkupRule.js").MarkupRule;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { createMarkupRule } from "../MarkupRule.js";
|
|
3
3
|
import { BLOCK_CONTENT_REGEXP, createBlockRegExp } from "../util/regexp.js";
|
|
4
|
-
import { createMarkupRule } from "../util/rule.js";
|
|
5
4
|
const PREFIX = ">";
|
|
6
5
|
const INDENT = new RegExp(`^${PREFIX}`, "gm");
|
|
7
|
-
export const BLOCKQUOTE_REGEXP = createBlockRegExp(`${PREFIX}${BLOCK_CONTENT_REGEXP}`);
|
|
8
6
|
/**
|
|
9
7
|
* Blockquote block.
|
|
10
8
|
* - `>` quote character followed by zero or more spaces.
|
|
11
9
|
* - No spaces can appear before the `>` quote character.
|
|
12
10
|
* - Quote block is only broken by `\n\n` two newline characters.
|
|
13
11
|
*/
|
|
14
|
-
export const BLOCKQUOTE_RULE = createMarkupRule(
|
|
12
|
+
export const BLOCKQUOTE_RULE = createMarkupRule(createBlockRegExp(`(?<quote>${PREFIX}${BLOCK_CONTENT_REGEXP})`), (key, { quote }, parser) => _jsx("blockquote", { children: parser.parse(quote.replace(INDENT, ""), "block") }, key), ["block", "list"]);
|
package/markup/rule/code.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* - Text surrounded by one or more "`" backtick tilde characters.
|
|
4
4
|
* - Unlike strong/emphasis first or last character of the element can be space, (e.g. `- abc -` will not work).
|
|
5
5
|
* - Closing characters must exactly match opening characters.
|
|
6
|
+
* - Works inside link text too, e.g. `` [`code`](url) ``.
|
|
6
7
|
* - Same as Markdown syntax.
|
|
7
8
|
*/
|
|
8
|
-
export declare const CODE_RULE: import("../
|
|
9
|
+
export declare const CODE_RULE: import("../MarkupRule.js").MarkupRule;
|
package/markup/rule/code.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { getRegExp } from "../../util/regexp.js";
|
|
3
|
+
import { createMarkupRule } from "../MarkupRule.js";
|
|
3
4
|
import { BLOCK_CONTENT_REGEXP } from "../util/regexp.js";
|
|
4
|
-
import { createMarkupRule } from "../util/rule.js";
|
|
5
|
-
const CODE_REGEXP = getRegExp(`(?<fence>\`+)(?<code>${BLOCK_CONTENT_REGEXP})\\k<fence>`);
|
|
6
5
|
/**
|
|
7
6
|
* Inline code.
|
|
8
7
|
* - Text surrounded by one or more "`" backtick tilde characters.
|
|
9
8
|
* - Unlike strong/emphasis first or last character of the element can be space, (e.g. `- abc -` will not work).
|
|
10
9
|
* - Closing characters must exactly match opening characters.
|
|
10
|
+
* - Works inside link text too, e.g. `` [`code`](url) ``.
|
|
11
11
|
* - Same as Markdown syntax.
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
// Priority 10: code is a higher-precedence tier, resolved and masked before links/emphasis, so a
|
|
14
|
+
// code span that straddles a link delimiter wins and the link cannot form across it.
|
|
15
|
+
export const CODE_RULE = createMarkupRule(getRegExp(`(?<fence>\`+)(?<code>${BLOCK_CONTENT_REGEXP})\\k<fence>`), (key, { code }) => _jsx("code", { children: code }, key), ["inline", "list", "link"], 10);
|
package/markup/rule/fenced.d.ts
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* - If there's no closing fence the code block will run to the end of the current string.
|
|
8
8
|
* - Markdown-style four-space indent syntax is not supported (only fenced code since it's less confusing and more common).
|
|
9
9
|
*/
|
|
10
|
-
export declare const FENCED_RULE: import("../
|
|
10
|
+
export declare const FENCED_RULE: import("../MarkupRule.js").MarkupRule;
|
package/markup/rule/fenced.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createMarkupRule } from "../MarkupRule.js";
|
|
2
3
|
import { BLOCK_CONTENT_REGEXP, BLOCK_START_REGEXP, createBlockRegExp, LINE_CONTENT_REGEXP, LINE_SPACE_REGEXP } from "../util/regexp.js";
|
|
3
|
-
import { createMarkupRule } from "../util/rule.js";
|
|
4
4
|
const FENCE = "`{3,}|~{3,}";
|
|
5
|
-
const FENCED_REGEXP = createBlockRegExp(`(?<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
5
|
/**
|
|
11
6
|
* Fenced code blocks
|
|
12
7
|
* - Same as Markdown syntax.
|
|
@@ -16,4 +11,5 @@ const FENCED_REGEXP = createBlockRegExp(`(?<code>${BLOCK_CONTENT_REGEXP})`,
|
|
|
16
11
|
* - If there's no closing fence the code block will run to the end of the current string.
|
|
17
12
|
* - Markdown-style four-space indent syntax is not supported (only fenced code since it's less confusing and more common).
|
|
18
13
|
*/
|
|
19
|
-
export const FENCED_RULE = createMarkupRule(
|
|
14
|
+
export const FENCED_RULE = createMarkupRule(createBlockRegExp(`(?<code>${BLOCK_CONTENT_REGEXP})`, `${BLOCK_START_REGEXP}(?<fence>${FENCE}) *(?<title>${LINE_CONTENT_REGEXP})\n`, // Starts with the fence
|
|
15
|
+
`(?:${LINE_SPACE_REGEXP}*\n\\k<fence>(?:\\s*\\n)?|$)`), (key, { title, code }) => (_jsx("pre", { children: _jsx("code", { title: title?.trim() || undefined, children: code.trim() }) }, key)), ["block", "list"], 10);
|
package/markup/rule/heading.d.ts
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* - `#` must be the first character on the line.
|
|
5
5
|
* - Markdown's underline syntax is not supported (for simplification).
|
|
6
6
|
*/
|
|
7
|
-
export declare const HEADING_RULE: import("../
|
|
7
|
+
export declare const HEADING_RULE: import("../MarkupRule.js").MarkupRule;
|
package/markup/rule/heading.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { createMarkupRule } from "../MarkupRule.js";
|
|
3
3
|
import { createLineRegExp, LINE_CONTENT_REGEXP, LINE_SPACE_REGEXP } from "../util/regexp.js";
|
|
4
|
-
import { createMarkupRule } from "../util/rule.js";
|
|
5
|
-
const HEADING_REGEXP = createLineRegExp(`(?<prefix>#{1,6})(?:${LINE_SPACE_REGEXP}+(?<heading>${LINE_CONTENT_REGEXP}))?`);
|
|
6
4
|
/**
|
|
7
5
|
* Headings are single line only (don't allow multiline).
|
|
8
6
|
* - `#` 1-6 hashes, then one or more spaces, then the title.
|
|
9
7
|
* - `#` must be the first character on the line.
|
|
10
8
|
* - Markdown's underline syntax is not supported (for simplification).
|
|
11
9
|
*/
|
|
12
|
-
export const HEADING_RULE = createMarkupRule(
|
|
10
|
+
export const HEADING_RULE = createMarkupRule(createLineRegExp(`(?<prefix>#{1,6})(?:${LINE_SPACE_REGEXP}+(?<heading>${LINE_CONTENT_REGEXP}))?`), (key, { prefix, heading = "" }, parser) => {
|
|
13
11
|
// The hash count picks the heading level; cast the dynamic tag to the known `h1`–`h6` set.
|
|
14
12
|
const Heading = `h${prefix.length}`;
|
|
15
|
-
return _jsx(Heading, { children:
|
|
13
|
+
return _jsx(Heading, { children: parser.parse(heading.trim(), "inline") }, key);
|
|
16
14
|
}, ["block"]);
|
package/markup/rule/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { MarkupRules } from "../util/rule.js";
|
|
1
|
+
import type { MarkupRules } from "../MarkupRule.js";
|
|
3
2
|
/** Markup rules that work in a block context. */
|
|
4
3
|
export declare const MARKUP_RULES_BLOCK: MarkupRules;
|
|
5
4
|
/** Markup rules that work in an inline context. */
|
|
@@ -11,27 +10,8 @@ export declare const MARKUP_RULES_INLINE: MarkupRules;
|
|
|
11
10
|
* 1. Syntax is more intuitive (e.g. `*strong*` always uses `*` asterisk and `_em_` always uses `_` underscore, and URLs are always autolinked).
|
|
12
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 />`).
|
|
13
12
|
* 3. Don't support fussy fragile syntax that lets users make mistakes (e.g. literal HTML tags or `&` character entities).
|
|
14
|
-
*
|
|
15
|
-
* @todo Default rules support "list items containing paragraphs" syntax (CommonMark calls this loose lists).
|
|
16
|
-
* - i.e. Lists can include `\n\n` double line breaks, and wrap all their contents in `<p>` entities, i.e. childContext is "block"
|
|
17
|
-
* - Hard because you have to capture the entire list including `\n\n`, so there's no obvious place to end it.
|
|
18
|
-
* - If there are breaks then any sub-lines need to be indented by two or more spaces otherwise it will break the list.
|
|
19
|
-
* - Make reference lists support this loose format too.
|
|
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
13
|
*/
|
|
32
14
|
export declare const MARKUP_RULES: MarkupRules;
|
|
33
|
-
/** Default markup options — uses `MARKUP_RULES` with no other overrides. */
|
|
34
|
-
export declare const MARKUP_OPTIONS: MarkupOptions;
|
|
35
15
|
export * from "./blockquote.js";
|
|
36
16
|
export * from "./code.js";
|
|
37
17
|
export * from "./fenced.js";
|
package/markup/rule/index.js
CHANGED
|
@@ -22,7 +22,13 @@ export const MARKUP_RULES_BLOCK = [
|
|
|
22
22
|
PARAGRAPH_RULE,
|
|
23
23
|
];
|
|
24
24
|
/** Markup rules that work in an inline context. */
|
|
25
|
-
export const MARKUP_RULES_INLINE = [
|
|
25
|
+
export const MARKUP_RULES_INLINE = [
|
|
26
|
+
CODE_RULE, //
|
|
27
|
+
LINK_RULE,
|
|
28
|
+
AUTOLINK_RULE,
|
|
29
|
+
INLINE_RULE,
|
|
30
|
+
LINEBREAK_RULE,
|
|
31
|
+
];
|
|
26
32
|
/**
|
|
27
33
|
* Default markup rules
|
|
28
34
|
*
|
|
@@ -30,27 +36,11 @@ export const MARKUP_RULES_INLINE = [CODE_RULE, LINK_RULE, AUTOLINK_RULE, INLINE_
|
|
|
30
36
|
* 1. Syntax is more intuitive (e.g. `*strong*` always uses `*` asterisk and `_em_` always uses `_` underscore, and URLs are always autolinked).
|
|
31
37
|
* 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 />`).
|
|
32
38
|
* 3. Don't support fussy fragile syntax that lets users make mistakes (e.g. literal HTML tags or `&` character entities).
|
|
33
|
-
*
|
|
34
|
-
* @todo Default rules support "list items containing paragraphs" syntax (CommonMark calls this loose lists).
|
|
35
|
-
* - i.e. Lists can include `\n\n` double line breaks, and wrap all their contents in `<p>` entities, i.e. childContext is "block"
|
|
36
|
-
* - Hard because you have to capture the entire list including `\n\n`, so there's no obvious place to end it.
|
|
37
|
-
* - If there are breaks then any sub-lines need to be indented by two or more spaces otherwise it will break the list.
|
|
38
|
-
* - Make reference lists support this loose format too.
|
|
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
39
|
*/
|
|
51
|
-
export const MARKUP_RULES = [
|
|
52
|
-
|
|
53
|
-
|
|
40
|
+
export const MARKUP_RULES = [
|
|
41
|
+
...MARKUP_RULES_BLOCK, //
|
|
42
|
+
...MARKUP_RULES_INLINE,
|
|
43
|
+
];
|
|
54
44
|
export * from "./blockquote.js";
|
|
55
45
|
export * from "./code.js";
|
|
56
46
|
export * from "./fenced.js";
|
package/markup/rule/inline.d.ts
CHANGED
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
* - Closing characters must exactly match opening characters.
|
|
12
12
|
* - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
|
|
13
13
|
*/
|
|
14
|
-
export declare const INLINE_RULE: import("../
|
|
14
|
+
export declare const INLINE_RULE: import("../MarkupRule.js").MarkupRule;
|