summaryrefslogtreecommitdiffhomepage
path: root/dlang/src/write/rgx.d
blob: f32df85e3e02c0fc5ae437d01f446c31ad8616d7 (plain)
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");
}