Skip to content

Commit a826936

Browse files
committed
Added initial support to CommonMark.
Support for Strike, Ins, Mark and Sub tags. Rewrite of Dialect selection. Bug fixes. Signed-off-by: Miguel A. Risco-Castillo
1 parent 21e39c1 commit a826936

File tree

10 files changed

+342
-152
lines changed

10 files changed

+342
-152
lines changed

README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ At present the following dialects of markdown are supported:
1515
* Enhanced TxtMark dialect
1616
(translated from <https://github.com/rjeschke/txtmark>)
1717

18+
* Initial support for CommonMark dialect
19+
(translated from <http://commonmark.org/>)
20+
1821
Wishlist: PEGDown (Github dialect), CommonMark, etc.
1922

2023
All you need to use the library is FPC version 3.0.4 or newer.
2124

22-
## Using the Library
2325

26+
Using the Library
27+
-----------------
2428

2529
Declare a variable of the class TMarkdownProcessor:
2630

@@ -35,20 +39,25 @@ Decide whether you want to allow active content
3539

3640
md.UnSafe := true;
3741

38-
Note: you should only set this to true if you *need* to - active content can be a signficant safety/security issue.
42+
Note: you should only set this to true if you *need* to - active content can be a significant safety/security issue.
3943

4044
Generate HTML fragments from Markdown content:
4145

4246
html := md.process(markdown);
4347

4448
Note that the HTML returned is an HTML fragment, not a full HTML page.
4549

46-
Do not forget to dispose the object after the use:
50+
Do not forget to dispose of the object after the use:
4751

4852
md.free
4953

50-
## License
54+
Examples
55+
--------
56+
The demo folder contains two demonstrative [Lazarus](http://www.lazarus-ide.org/) programs,
57+
the most advanced, `MarkdownHTML`, needs the [HTMLViewer](https://github.com/BerndGabriel/HtmlViewer) control.
5158

59+
License
60+
-------
5261
Copyright (C) Miguel A. Risco-Castillo
5362

5463
FPC-markdown implementation is a fork of Grahame Grieve pascal port

demos/MarkDownHtml/MarkDownHtml.lpi

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,19 @@
1111
<UseXPManifest Value="True"/>
1212
<XPManifest>
1313
<DpiAware Value="True"/>
14+
<TextName Value="uEGroup.FPCMarkDown.TestHtmlConveter"/>
15+
<TextDesc Value="Test Markdown Processor for FPC."/>
1416
</XPManifest>
1517
<Icon Value="0"/>
1618
</General>
19+
<VersionInfo>
20+
<UseVersionInfo Value="True"/>
21+
<MinorVersionNr Value="2"/>
22+
<RevisionNr Value="3"/>
23+
<BuildNr Value="18"/>
24+
<Attributes pvaPreRelease="True"/>
25+
<StringTable ProductVersion="0.0.0.0"/>
26+
</VersionInfo>
1727
<BuildModes Count="3">
1828
<Item1 Name="Default" Default="True"/>
1929
<Item2 Name="Debug">
@@ -142,4 +152,17 @@
142152
<CustomOptions Value="-dBorland -dVer150 -dDelphi7 -dCompiler6_Up -dPUREPASCAL"/>
143153
</Other>
144154
</CompilerOptions>
155+
<Debugging>
156+
<Exceptions Count="3">
157+
<Item1>
158+
<Name Value="EAbort"/>
159+
</Item1>
160+
<Item2>
161+
<Name Value="ECodetoolError"/>
162+
</Item2>
163+
<Item3>
164+
<Name Value="EFOpenError"/>
165+
</Item3>
166+
</Exceptions>
167+
</Debugging>
145168
</CONFIG>

demos/MarkDownHtml/MarkDownHtmlu.lfm

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
object MainForm: TMainForm
2-
Left = 945
2+
Left = 1041
33
Height = 499
4-
Top = 273
4+
Top = 340
55
Width = 790
66
Caption = 'Test MarkDown Convertion'
77
ClientHeight = 499
@@ -547,7 +547,7 @@ object MainForm: TMainForm
547547
'Basic Information'
548548
'-----------------'
549549
''
550-
'This is a Pascal (`FPC`) library that processes markdown to HTML.'
550+
'This is a Pascal (FPC) library that processes markdown to HTML.'
551551
'At present the following dialects of markdown are supported:'
552552
''
553553
'* The Daring Fireball dialect'
@@ -556,6 +556,9 @@ object MainForm: TMainForm
556556
'* Enhanced TxtMark dialect'
557557
' (translated from <https://github.com/rjeschke/txtmark>)'
558558
''
559+
'* Initial support for CommonMark dialect'
560+
' (translated from <http://commonmark.org/>)'
561+
''
559562
'Wishlist: PEGDown (Github dialect), CommonMark, etc.'
560563
''
561564
'All you need to use the library is FPC version 3.0.4 or newer.'
@@ -576,15 +579,15 @@ object MainForm: TMainForm
576579
''
577580
' md.UnSafe := true;'
578581
' '
579-
'Note: you should only set this to true if you *need* to - active content can be a signficant safety/security issue. '
582+
'Note: you should only set this to true if you *need* to - active content can be a significant safety/security issue. '
580583
' '
581584
'Generate HTML fragments from Markdown content:'
582585
''
583586
' html := md.process(markdown); '
584587
' '
585588
'Note that the HTML returned is an HTML fragment, not a full HTML page. '
586589
' '
587-
'Do not forget to dispose the object after the use:'
590+
'Do not forget to dispose of the object after the use:'
588591
''
589592
' md.free'
590593
''
@@ -629,6 +632,7 @@ object MainForm: TMainForm
629632
MouseLinkColor.Foreground = clBlue
630633
LineHighlightColor.Background = clCream
631634
LineHighlightColor.Foreground = clNone
635+
TabWidth = 4
632636
inline SynLeftGutterPartList1: TSynGutterPartList
633637
object SynGutterMarks1: TSynGutterMarks
634638
Width = 24

demos/MarkDownHtml/MarkDownHtmlu.pas

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ interface
66

77
uses
88
Classes, SysUtils, LazFileUtils, SynEdit, SynHighlighterHTML, Forms, Controls,
9-
Graphics, Dialogs, StdCtrls, ExtCtrls, Clipbrd, MarkdownProcessor, LCLIntf,
10-
ComCtrls, Buttons, StrUtils, HtmlView, HtmlGlobals, HTMLUn2;
9+
Graphics, Dialogs, StdCtrls, ExtCtrls, Clipbrd, MarkdownProcessor, MarkdownUtils,
10+
LCLIntf, ComCtrls, Buttons, StrUtils, HtmlView, HtmlGlobals, HTMLUn2;
1111

1212
type
1313

@@ -140,7 +140,7 @@ procedure TMainForm.FormCreate(Sender: TObject);
140140
var
141141
i:integer;
142142
begin
143-
md := TMarkdownProcessor.createDialect(mdTxtMark);
143+
md := TMarkdownProcessor.createDialect(mdCommonMark);
144144
md.UnSafe := false;
145145
RootPath:=GetTempDir;
146146
I:=0;

fpc_markdown.lpk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
5454
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5555
See the License for the specific language governing permissions and
5656
limitations under the License."/>
57-
<Version Major="1" Release="1"/>
57+
<Version Major="1" Minor="1" Release="1" Build="3"/>
5858
<Files Count="5">
5959
<Item1>
6060
<Filename Value="source\MarkdownProcessor.pas"/>
@@ -66,7 +66,7 @@ limitations under the License."/>
6666
</Item2>
6767
<Item3>
6868
<Filename Value="source\markdowntxtmark.pas"/>
69-
<UnitName Value="markdowntxtmark"/>
69+
<UnitName Value="MarkdownTxtMark"/>
7070
</Item3>
7171
<Item4>
7272
<Filename Value="source\MarkdownUtils.pas"/>

source/MarkdownCommonMark.pas

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ implementation
4646
constructor TMarkdownCommonMark.Create;
4747
begin
4848
inherited;
49+
Config.Dialect:=mdCommonMark;
4950
end;
5051

5152
destructor TMarkdownCommonMark.Destroy;
5253
begin
53-
5454
inherited;
5555
end;
5656

source/MarkdownDaringFireball.pas

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,24 @@ interface
2727
SysUtils, Classes, TypInfo,
2828
MarkdownProcessor, MarkdownUtils;
2929

30-
3130
type
3231

3332
TMarkdownDaringFireball = class(TMarkdownProcessor)
3433
private
35-
FConfig: TConfiguration;
34+
// Config: TConfiguration;
3635
Femitter: TEmitter;
3736
FuseExtensions: boolean;
3837
function readLines(reader : TReader): TBlock;
3938
procedure initListBlock(root: TBlock);
4039
procedure recurse(root: TBlock; listMode: boolean);
41-
4240
protected
4341
function GetUnSafe: boolean; override;
4442
procedure SetUnSafe(const value: boolean); override;
4543
public
4644
Constructor Create;
4745
Destructor Destroy; override;
4846
function process(source: String): String; override;
49-
property config: TConfiguration read FConfig;
50-
47+
// property config: TConfiguration read Config;
5148
end;
5249

5350
implementation
@@ -57,20 +54,20 @@ implementation
5754
constructor TMarkdownDaringFireball.Create;
5855
begin
5956
inherited Create;
60-
FConfig := TConfiguration.Create(true);
57+
Config := TConfiguration.Create(true);
6158
Femitter := TEmitter.Create(config);
6259
end;
6360

6461
destructor TMarkdownDaringFireball.Destroy;
6562
begin
66-
FConfig.Free;
63+
Config.Free;
6764
Femitter.Free;
6865
inherited;
6966
end;
7067

7168
function TMarkdownDaringFireball.GetUnSafe: boolean;
7269
begin
73-
result := not FConfig.safeMode;
70+
result := not Config.safeMode;
7471
end;
7572

7673
procedure TMarkdownDaringFireball.initListBlock(root: TBlock);
@@ -82,7 +79,7 @@ procedure TMarkdownDaringFireball.initListBlock(root: TBlock);
8279
line := line.next;
8380
while (line <> nil) do
8481
begin
85-
t := line.getLineType(FConfig);
82+
t := line.getLineType(Config);
8683
if ((t = ltOLIST) or (t = ltULIST) or (not line.isEmpty and (line.prevEmpty and (line.leading = 0) and not((t = ltOLIST) or (t = ltULIST))))) then
8784
root.split(line.previous).type_ := btLIST_ITEM;
8885
line := line.next;
@@ -96,8 +93,7 @@ function TMarkdownDaringFireball.process(source: String): String;
9693
parent, block: TBlock;
9794
rdr : TReader;
9895
begin
99-
FuseExtensions := config.forceExtendedProfile;
100-
Femitter.FuseExtensions:=config.forceExtendedProfile;
96+
FuseExtensions := Config.isDialect([mdTxtMark,mdCommonMark]);
10197
rdr := TReader.Create(source);
10298
try
10399
out_ := TStringBuilder.Create;
@@ -175,7 +171,7 @@ function TMarkdownDaringFireball.readLines(reader : TReader): TBlock;
175171
c := reader.read();
176172
end;
177173
else
178-
if (c <> '<') or (not FConfig.panicMode) then
174+
if (c <> '<') or (not Config.panicMode) then
179175
begin
180176
inc(position);
181177
sb.append(c);
@@ -259,8 +255,7 @@ function TMarkdownDaringFireball.readLines(reader : TReader): TBlock;
259255
if LowerCase(link) = 'extended' then
260256
begin
261257
FuseExtensions:=true;
262-
Config.forceExtendedProfile:=true;
263-
Femitter.FuseExtensions := true;
258+
Config.Dialect:=mdTxtMark;
264259
end;
265260
lastLinkRef := nil;
266261
end
@@ -324,8 +319,8 @@ procedure TMarkdownDaringFireball.recurse(root: TBlock; listMode: boolean);
324319
line := root.lines;
325320
if (listMode) then
326321
begin
327-
root.removeListIndent(FConfig);
328-
if (FuseExtensions and (root.lines <> nil) and (root.lines.getLineType(FConfig) <> ltCODE)) then
322+
root.removeListIndent(Config);
323+
if (Config.isDialect([mdTxtMark]) and (root.lines <> nil) and (root.lines.getLineType(Config) <> ltCODE)) then
329324
root.id := root.lines.stripID();
330325
end;
331326

@@ -336,14 +331,14 @@ procedure TMarkdownDaringFireball.recurse(root: TBlock; listMode: boolean);
336331

337332
while (line <> nil) do
338333
begin
339-
type_ := line.getLineType(FConfig);
334+
type_ := line.getLineType(Config);
340335
case type_ of
341336
ltOTHER:
342337
begin
343338
wasEmpty := line.prevEmpty;
344339
while (line <> nil) and (not line.isEmpty) do
345340
begin
346-
t := line.getLineType(FConfig);
341+
t := line.getLineType(Config);
347342
if (listMode or FuseExtensions) and (t in [ltOLIST, ltULIST]) then
348343
break;
349344
if (FuseExtensions and (t in [ltCODE, ltFENCED_CODE])) then
@@ -403,7 +398,7 @@ procedure TMarkdownDaringFireball.recurse(root: TBlock; listMode: boolean);
403398
begin
404399
while (line <> nil) do
405400
begin
406-
if (not line.isEmpty and (line.prevEmpty and (line.leading = 0) and (line.getLineType(FConfig) <> ltBQUOTE))) then
401+
if (not line.isEmpty and (line.prevEmpty and (line.leading = 0) and (line.getLineType(Config) <> ltBQUOTE))) then
407402
break;
408403
line := line.next;
409404
end;
@@ -431,7 +426,7 @@ procedure TMarkdownDaringFireball.recurse(root: TBlock; listMode: boolean);
431426
line := line.next;
432427
while (line <> nil) do
433428
begin
434-
if (line.getLineType(FConfig) = ltFENCED_CODE) then
429+
if (line.getLineType(Config) = ltFENCED_CODE) then
435430
break;
436431
// TODO ... is this really necessary? Maybe add a special flag?
437432
line := line.next;
@@ -446,7 +441,7 @@ procedure TMarkdownDaringFireball.recurse(root: TBlock; listMode: boolean);
446441
block.type_ := btFENCED_CODE;
447442
block.meta := TUtils.getMetaFromFence(block.lines.value);
448443
block.lines.setEmpty();
449-
if (block.lineTail.getLineType(FConfig) = ltFENCED_CODE) then
444+
if (block.lineTail.getLineType(Config) = ltFENCED_CODE) then
450445
block.lineTail.setEmpty();
451446
block.removeSurroundingEmptyLines();
452447
end;
@@ -463,7 +458,7 @@ procedure TMarkdownDaringFireball.recurse(root: TBlock; listMode: boolean);
463458
block.hlDepth := 1
464459
else
465460
block.hlDepth := 2;
466-
if (FuseExtensions) then
461+
if Config.isDialect([mdTxtMark]) then
467462
block.id := block.lines.stripID();
468463
block.transfromHeadline();
469464
root.removeLeadingEmptyLines();
@@ -473,7 +468,7 @@ procedure TMarkdownDaringFireball.recurse(root: TBlock; listMode: boolean);
473468
begin
474469
while (line <> nil) do
475470
begin
476-
t := line.getLineType(FConfig);
471+
t := line.getLineType(Config);
477472
if (not line.isEmpty and (line.prevEmpty and (line.leading = 0) and (not(t = type_)))) then
478473
break;
479474
line := line.next;
@@ -508,7 +503,7 @@ procedure TMarkdownDaringFireball.recurse(root: TBlock; listMode: boolean);
508503

509504
procedure TMarkdownDaringFireball.SetUnSafe(const value: boolean);
510505
begin
511-
FConfig.safeMode := not value;
506+
Config.safeMode := not value;
512507
end;
513508

514509
end.

0 commit comments

Comments
 (0)