1 ------------------------------------------------------------------------------
4 -- Copyright (C) 2007-2008 --
7 -- This library is free software; you can redistribute it and/or modify --
8 -- it under the terms of the GNU General Public License as published by --
9 -- the Free Software Foundation; either version 2 of the License, or (at --
10 -- your option) any later version. --
12 -- This library is distributed in the hope that it will be useful, but --
13 -- WITHOUT ANY WARRANTY; without even the implied warranty of --
14 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --
15 -- General Public License for more details. --
17 -- You should have received a copy of the GNU General Public License --
18 -- along with this library; if not, write to the Free Software Foundation, --
19 -- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --
20 ------------------------------------------------------------------------------
22 with Diouzhtu
.Attribute
;
24 with Ada
.Strings
.Unbounded
;
26 package body Diouzhtu
.Block
is
29 use Ada
.Strings
.Unbounded
;
33 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
35 -- bq. Blockquote element
38 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
40 -- <h1>, <h2>, ... element
43 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
45 -- list element <ul>, <ol>
48 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
53 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
62 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
64 Extract
: constant Pattern_Matcher
:=
65 Compile
(Expression
=> "^bq" & Attribute
.Get_Pattern
& "\.\s(.*)$",
66 Flags
=> Case_Insensitive
+ Single_Line
);
67 Count
: constant Match_Count
:= Paren_Count
(Extract
);
68 Matches
: Match_Array
(0 .. Paren_Count
(Extract
));
69 Result
: Unbounded_String
:= Null_Unbounded_String
;
71 Match
(Extract
, Block
, Matches
);
72 if Matches
(0) = No_Match
then
73 return Parse
(Wiki
=> Wiki
,
79 Result
:= To_Unbounded_String
("<blockquote");
81 if Matches
(1) /= No_Match
then
82 Append
(Result
, Attribute
.Extract
83 (Block
(Matches
(1).First
.. Matches
(1).Last
)));
86 if Matches
(Count
) /= No_Match
then
89 Parse
(Wiki
, Inline_Level
,
90 Block
(Matches
(Count
).First
.. Matches
(Count
).Last
)) &
91 "</p></blockquote>" & ASCII
.LF
);
93 return To_String
(Result
);
102 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
105 Extract
: constant Pattern_Matcher
:=
106 Compile
(Expression
=> "^h(\d)" & Attribute
.Get_Pattern
& "\.\s(.*)$",
107 Flags
=> Case_Insensitive
+ Single_Line
);
110 Count
: constant Match_Count
:= Paren_Count
(Extract
);
111 Matches
: Match_Array
(0 .. Paren_Count
(Extract
));
112 Result
: Unbounded_String
:= Null_Unbounded_String
;
115 -- Search for block level
116 Match
(Extract
, Block
, Matches
);
117 if Matches
(0) = No_Match
then
118 return Parse
(Wiki
=> Wiki
,
119 Level
=> Block_Level
,
124 Header
:= Block
(Matches
(1).First
);
126 Result
:= To_Unbounded_String
129 if Matches
(2) /= No_Match
then
130 Append
(Result
, Attribute
.Extract
131 (Block
(Matches
(2).First
.. Matches
(2).Last
)));
134 if Matches
(Count
) /= No_Match
then
135 Append
(Result
, ">" &
136 Parse
(Wiki
, Inline_Level
,
138 (Count
).First
.. Matches
(Count
).Last
)) &
139 "</h" & Header
& ">" & ASCII
.LF
);
142 return To_String
(Result
);
146 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
149 type Elements
is array (1 .. 2) of String (1 .. 2);
150 type Tags
is array (1 .. 2) of Character;
152 Element
: constant Elements
:= Elements
'(1 => "ol", 2 => "ul");
153 Tag : constant Tags := Tags'(1 => '#', 2 => '*');
154 Indentation
: constant String := " ";
156 Get_Element
: String (1 .. 2);
158 Result
: Unbounded_String
:= Null_Unbounded_String
;
160 type List_Level
is new Natural;
163 (Wiki
: in Wiki_Information
;
165 Level
: in out List_Level
;
166 Line_Level
: in List_Level
;
167 First_Line
: in Boolean := False);
169 function Get_Current_Level
(Line
: in String) return List_Level
;
171 function Indent
(Level
: in List_Level
) return String;
173 -----------------------
174 -- Get_Current_Level --
175 -----------------------
177 function Get_Current_Level
(Line
: in String) return List_Level
is
178 Level
: List_Level
:= 0;
181 for K
in Line
'Range loop
182 exit Get_Level
when Block
(K
) /= Get_Tag
;
186 end Get_Current_Level
;
192 function Indent
(Level
: in List_Level
) return String is
193 pragma Warnings
(Off
);
197 N
:= 2 * (Positive (Level
) - 1);
198 return To_String
(N
* Indentation
);
208 (Wiki
: in Wiki_Information
;
210 Level
: in out List_Level
;
211 Line_Level
: in List_Level
;
212 First_Line
: in Boolean := False) is
213 pragma Warnings
(Off
);
215 if Line_Level
> Level
then
216 if Line_Level
> 1 then
217 Append
(Result
, ASCII
.LF
);
220 Append
(Result
, Indent
(Level
)
221 & '<' & Get_Element
& '>' & ASCII
.LF
);
222 Parse_Line
(Wiki
, Line
, Level
, Line_Level
, First_Line
=> True);
224 elsif Line_Level
< Level
then
225 Append
(Result
, ASCII
.LF
& Indent
(Level
) & Indentation
226 & "</li>" & ASCII
.LF
& Indent
(Level
)
227 & "</" & Get_Element
& '>');
230 Parse_Line
(Wiki
, Line
, Level
, Line_Level
);
235 if not First_Line
then
236 Append
(Result
, ASCII
.LF
& Indent
(Level
) & Indentation
237 & "</li>" & ASCII
.LF
);
239 Append
(Result
, Indent
(Level
) & Indentation
);
240 Append_Last_Content
:
242 Content_First
: constant Positive :=
243 Line
'First + Natural (Level
) + 1;
244 Content_Last
: Positive := Line
'Last;
246 if Line
(Content_Last
) = ASCII
.LF
then
247 Content_Last
:= Content_Last
- 1;
253 Line
(Content_First
.. Content_Last
)));
254 end Append_Last_Content
;
260 if Block
'Length < 3 then
261 return Parse
(Wiki
=> Wiki
,
262 Level
=> Block_Level
,
267 Get_Tag
:= Block
(Block
'First);
269 if Block
(Block
'First .. Block
'First + 1) = Tag
(1) & ' ' then
270 Get_Element
:= Element
(1);
271 elsif Block
(Block
'First .. Block
'First + 1) = Tag
(2) & ' ' then
272 Get_Element
:= Element
(2);
274 return Parse
(Wiki
=> Wiki
,
275 Level
=> Block_Level
,
282 Last
: Positive := Block
'First;
283 Last_Level
: List_Level
:= 0; -- List_Level'First
285 for K
in Block
'Range loop
287 or else (Block
(K
) = ASCII
.LF
and then Block
(K
+ 1) = Get_Tag
)
291 Line
: constant String := Block
(Last
.. K
);
292 Line_Level
: constant List_Level
:= Get_Current_Level
(Line
);
294 Parse_Line
(Wiki
=> Wiki
,
297 Line_Level
=> Line_Level
);
299 end Parse_Current_Line
;
302 Parse_Line
(Wiki
=> Wiki
,
307 return To_String
(Result
) & ASCII
.LF
;
315 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
318 pragma Unreferenced
(Index
);
319 Extract
: constant Pattern_Matcher
:=
320 Compile
(Expression
=> "^p" & Attribute
.Get_Pattern
& "\.\s(.*)$",
321 Flags
=> Case_Insensitive
+ Single_Line
);
322 Count
: constant Match_Count
:= Paren_Count
(Extract
);
323 Matches
: Match_Array
(0 .. Paren_Count
(Extract
));
324 Result
: Unbounded_String
:= Null_Unbounded_String
;
326 Match
(Extract
, Block
, Matches
);
327 if Matches
(0) = No_Match
then
328 return "<p>" & Parse
(Wiki
, Inline_Level
, Block
) & "</p>" & ASCII
.LF
;
331 Result
:= To_Unbounded_String
("<p");
333 if Matches
(1) /= No_Match
then
334 Append
(Result
, Attribute
.Extract
335 (Block
(Matches
(1).First
.. Matches
(1).Last
)));
338 if Matches
(Count
) /= No_Match
then
342 Parse
(Wiki
, Inline_Level
,
343 Block
(Matches
(Count
).First
.. Matches
(Count
).Last
))
344 & "</p>" & ASCII
.LF
);
346 return To_String
(Result
);
353 procedure Register
is
355 Internal_Register
(Block_Level
, Header
'Access);
356 Internal_Register
(Block_Level
, List
'Access);
357 Internal_Register
(Block_Level
, Blockquote
'Access);
358 Internal_Register
(Block_Level
, Table
'Access);
359 Internal_Register
(Block_Level
, Paragraph
'Access);
367 (Wiki
: in Wiki_Information
; Index
: in Positive; Block
: in String)
371 Nb_Cols
: Natural := 0;
372 Nb_Rows
: Natural := 0;
373 Table_Block
: String := Block
;
374 Result
: Unbounded_String
:= Null_Unbounded_String
;
376 procedure Get_Dimension
;
377 -- Get maximum of cols and number of rows
383 procedure Get_Dimension
is
384 Line_Nb_Cols
: Natural := 0;
387 for I
in Table_Block
'Range loop
388 if Table_Block
(I
) = ASCII
.LF
then
389 if I
> Table_Block
'First + 1
390 and then Table_Block
(I
- 2 .. I
- 1) /= " |" then
391 -- A table line MUST end with |
394 if I
< Table_Block
'Last - 1
395 and then Table_Block
(I
+ 1 .. I
+ 2) /= "| " then
396 -- A table line MUST begin with |
399 if Line_Nb_Cols
> Nb_Cols
then
400 Nb_Cols
:= Line_Nb_Cols
;
402 Nb_Rows
:= Nb_Rows
+ 1;
406 if Table_Block
(I
) = '|' then
407 if (I
= Table_Block
'First or else
408 Table_Block
(I
- 1) = ' ' or else
409 Table_Block
(I
- 1) = ASCII
.LF
) and then
410 (I
= Table_Block
'Last or else
411 Table_Block
(I
+ 1) = ' ' or else
412 Table_Block
(I
+ 1) = ASCII
.LF
)
414 Line_Nb_Cols
:= Line_Nb_Cols
+ 1;
416 Table_Block
(I
) := ' ';
425 if Nb_Cols
= 0 or else Nb_Rows
= 0 then
428 Level
=> Block_Level
,
429 Content
=> Table_Block
,
435 Line_Cols
: Natural := 0;
436 Last_Position
: Natural := 0;
438 for K
in Table_Block
'Range loop
439 if Table_Block
(K
) = '|' then
440 if Line_Cols
> 0 and then Last_Position
+ 2 < K
- 2 then
442 (Result
, Parse
(Wiki
, Inline_Level
,
443 Table_Block
(Last_Position
+ 2 .. K
- 2)));
444 Append
(Result
, "</td>" & ASCII
.LF
);
447 if Line_Cols
< Nb_Cols
- 1 then
448 Append
(Result
, "<td>");
450 Line_Cols
:= Line_Cols
+ 1;
454 if Table_Block
(K
) = ASCII
.LF
or else K
= Table_Block
'Last then
455 if Line_Cols
< Nb_Cols
then
458 Nb_Empty_Cols
: constant Natural := Nb_Cols
- Line_Cols
;
459 Empty_Col
: constant String := "<td></td>" & ASCII
.LF
;
461 Append
(Result
, "</td>" & ASCII
.LF
&
462 (Nb_Empty_Cols
- 1) * Empty_Col
);
466 if K
/= Table_Block
'Last then
467 Append
(Result
, "</tr>" & ASCII
.LF
& "<tr>" & ASCII
.LF
);
469 Append
(Result
, "</tr>" & ASCII
.LF
);
476 return "<table>" & ASCII
.LF
& "<tr>" & ASCII
.LF
477 & To_String
(Result
) & "</table>" & ASCII
.LF
;