1:- module(md_links, [
2 md_links/3, 3 md_links/2, 4 md_link/3 5]).
14:- use_module(library(dcg/basics)). 15:- use_module(md_line). 16
18
19:- thread_local(link_definition/3).
26md_link(Id, Url, Title):-
27 link_definition(Id, Url, Title).
35md_links(CodesIn, CodesOut):-
36 retractall(link_definition(_, _, _)),
37 md_links(CodesIn, CodesOut, Links),
38 maplist(assert_link, Links).
39
40assert_link(link(Id, Url, Title)):-
41 assertz(link_definition(Id, Url, Title)).
48md_links(CodesIn, CodesOut, Links):-
49 phrase(links_begin(TmpCodes, TmpLinks), CodesIn),
50 CodesOut = TmpCodes,
51 Links = TmpLinks.
52
53links_begin(Codes, [Link|Links]) -->
54 link(Link), !, links(Codes, Links).
55
56links_begin(Codes, Links) -->
57 links(Codes, Links).
58
59links([Code|Codes], Links) -->
60 [Code], { \+code_type(Code, end_of_line) }, !,
61 links(Codes, Links).
62
63links(Codes, [Link|Links]) -->
64 ln_full, link(Link), !, links(Codes, Links).
65
66links([0'\n|Codes], Links) -->
67 ln_full, !, links(Codes, Links).
68
69links([], []) --> eos, !.
70
71ln_full --> "\r\n", !.
72ln_full --> "\n", !.
73ln_full --> "\r".
74
78
79link(link(Id, Url, Title)) -->
80 link_indent, link_id(Id),
81 whites, link_url(Url),
82 whites, link_title(Title).
83
87
88link_indent --> " ".
89link_indent --> " ".
90link_indent --> " ".
91link_indent --> "".
92
96
97link_title(Title) -->
98 link_title_same_line(Title), !.
99
100link_title(Title) -->
101 ln_full, whites, link_title_same_line(Title), !.
102
103link_title('') --> "".
104
105link_title_same_line(Title) -->
106 "'", !, inline_string(Codes), "'",
107 whites, lookahead_ln_or_eos,
108 { atom_codes(Title, Codes) }.
109
110link_title_same_line(Title) -->
111 "(", !, inline_string(Codes), ")",
112 whites, lookahead_ln_or_eos,
113 { atom_codes(Title, Codes) }.
114
115link_title_same_line(Title) -->
116 "\"", inline_string(Codes), "\"",
117 whites, lookahead_ln_or_eos,
118 { atom_codes(Title, Codes) }.
119
121
122link_id(Id) -->
123 "[", whites, inline_string(Codes), whites, "]:",
124 {
125 atom_codes(Tmp, Codes),
126 downcase_atom(Tmp, Id)
127 }.
128
130
131link_url(Url) -->
132 "<", !, inline_string(Codes), ">",
133 { atom_codes(Url, Codes) }.
134
135link_url(Url) -->
136 string_without([0'\n, 0'\t, 0' ], Codes),
137 { atom_codes(Url, Codes) }
Markdown reference link parser
Parses and removes reference links from the stream of symbol codes. Replaces line ends with canonical line ends. */