1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
module write.rgx;
/+ ↓ the internal markup, as regular expressions.
.
An object's text is *spine's internal representation*, not the author's
markup and not any output: the markers are single Unicode characters
chosen not to occur in text. A writer's first job is to turn them into
something the target format understands, so every writer needs these
and they live in one place.
.
Taken from the specification's description of object text and matched
against spine's own outputs/io_out/rgx.d, which is normative. The
characters are load bearing: do not "tidy" them into ASCII.
+/
import std.regex;
static struct Rgx {
/+ ↓ spacing and line breaks +/
static nbsp_char = ctRegex!(`░`, "mg");
static br_line = ctRegex!(`\s*┘\s*`, "mg");
static br_line_inline = ctRegex!(`\s*┙\s*`, "mg");
static br_line_spaced = ctRegex!(`\s*┚\s*`, "mg");
/+ ↓ font face, each ⑆<mark>┨ text ┣<mark> +/
static inline_strike = ctRegex!(`⑆[-]┨(?P<text>.+?)┣[-]`, "mg");
static inline_insert = ctRegex!(`⑆[+]┨(?P<text>.+?)┣[+]`, "mg");
static inline_cite = ctRegex!(`⑆[‖]┨(?P<text>.+?)┣[‖]`, "mg");
static inline_emphasis = ctRegex!(`⑆[*]┨(?P<text>.+?)┣[*]`, "mg");
static inline_bold = ctRegex!(`⑆[!]┨(?P<text>.+?)┣[!]`, "mg");
static inline_italics = ctRegex!(`⑆[/]┨(?P<text>.+?)┣[/]`, "mg");
static inline_underscore = ctRegex!(`⑆[_]┨(?P<text>.+?)┣[_]`, "mg");
static inline_superscript = ctRegex!(`⑆\^┨(?P<text>.+?)┣\^`, "mg");
static inline_subscript = ctRegex!(`⑆[,]┨(?P<text>.+?)┣[,]`, "mg");
static inline_mono = ctRegex!(`⑆[■]┨(?P<text>.+?)┣[■]`, "mg");
/+ ↓ links and images. Capture 1 is the text, 3 the target without its
leading "#" where it has one +/
static inline_link = ctRegex!(`┥(?P<text>.+?)┝┤(?P<link>#?(\S+?))├`, "mg");
static inline_image = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>[a-zA-Z0-9._-]+?\.(?:jpg|gif|png)),w(?P<width>\d+)h(?P<height>\d+))\s*(?P<post>.*?┝┤.*?├)`, "mg");
/+ ↓ notes, carried inline in the object that refers to them +/
static inline_notes_al_gen = ctRegex!(`【.+?】`, "m");
static inline_notes_al_regular_number_note = ctRegex!(`【(?P<num>\d+)\s+(?P<note>.+?)\s*】`, "mg");
/+ ↓ and the same for a note marked with a run of stars or pluses
instead of a number, which the markup also allows +/
static inline_notes_al_all_note = ctRegex!(`【(?P<num>\d+|[*+]+[0-9]*)\s+(?P<note>.+?)\s*】`, "mg");
/+ ↓ tables: the object's text is rows and columns in one string +/
static table_delimiter_row = ctRegex!("[ ]*\n", "mg");
static table_delimiter_col = ctRegex!("[ ]*[┊][ ]*", "mg");
/+ ↓ the book index, whose entries carry their own links +/
static find_bookindex_ocn_link_and_comma = ctRegex!(`[, ]*┥.+?┝┤#?\S+?├`, "mg");
/+ ↓ end of *input*, not end of line: spine's table layout strips the
whole accumulated string after every cell +/
static trailing_whitespace_all = ctRegex!(`\s*$`);
static trailing_backslash = ctRegex!(`\s*\\`, "mg");
/+ ↓ a link before its url has been substituted in: the number is an index
into the object's .stow_link list, not a target +/
static inline_link_number_only = ctRegex!(`(?P<linked_text>┥.+?┝)┤(?P<num>[0-9]+)├`, "mg");
static inline_link_empty = ctRegex!(`┥(?P<text>.+?)┝┤├`, "mg");
/+ ↓ an anchor the markup placed in the text, ┃name┃ +/
static inline_link_anchor = ctRegex!(`┃(?P<anchor>\S+?)┃`, "mg");
/+ ↓ "¤" marks a link that is internal to the document collection, and
".fnSuffix" stands where an output's file suffix goes +/
static mark_internal_site_lnk = ctRegex!(`¤`, "mg");
static inline_seg_link = ctRegex!(`(¤)(?:.+?)\.fnSuffix`, "mg");
/+ ↓ the same target taken apart: the segment it names and whatever
follows it, which is what a segmented output needs +/
static internal_target = ctRegex!(`^¤(?P<seg>.+?)\.fnSuffix(?P<frag>.*)$`);
/+ ↓ an image's alt text, which the markup carries as a quoted string
following the image +/
static inline_image_alt = ctRegex!(`^\s*[“"](?P<alt>[^”"]*)[”"]`, "m");
/+ ↓ a line break the markup asked for, " \\" +/
static line_break = ctRegex!(` [\\]{2}`, "m");
/+ ↓ the leading markers of a line inside a group: indent, hang, bullet.
"_2 " is indent two, "_2*" a bullet at indent two, "_2_1 " a hanging
indent. They are line-leading and so anchored, with "m".
+/
static grouped_para_indent = ctRegex!(`^_(?P<indent>[1-9])[ ]`, "m");
static grouped_para_bullet = ctRegex!(`^_[*] `, "m");
static grouped_para_bullet_at = ctRegex!(`^_(?P<indent>[1-9])[*] `, "m");
static grouped_para_indent_hang = ctRegex!(`^_(?P<hang>[0-9])_(?P<indent>[0-9])[ ]`, "m");
/+ ↓ an internal link target as the abstraction writes it, with or without
the segment prefix a segmented output would use. Read to decide whether
a table of contents entry points at anything this writer renders. +/
static any_internal_target = ctRegex!(`┤(?:¤.+?\.fnSuffix)?#(?P<frag>[^├]+)├`, "mg");
/+ ↓ the four characters html reserves +/
static ampersand = ctRegex!(`[&]`, "mg");
static quotation = ctRegex!(`["]`, "mg");
static less_than = ctRegex!(`[<]`, "mg");
static greater_than = ctRegex!(`[>]`, "mg");
}
|