Skip to content

Commit 19dc440

Browse files
committed
Merge branch 'feature/155-save-snippet-info-as-markdown' into develop
Fixes #155
2 parents 005acb2 + 9c67d38 commit 19dc440

13 files changed

+1779
-14
lines changed

Src/ActiveText.UMarkdownRenderer.pas

Lines changed: 927 additions & 0 deletions
Large diffs are not rendered by default.

Src/CodeSnip.dpr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,10 @@ uses
377377
ClassHelpers.UActions in 'ClassHelpers.UActions.pas',
378378
USaveInfoMgr in 'USaveInfoMgr.pas',
379379
ClassHelpers.RichEdit in 'ClassHelpers.RichEdit.pas',
380-
UHTMLSnippetDoc in 'UHTMLSnippetDoc.pas';
380+
UHTMLSnippetDoc in 'UHTMLSnippetDoc.pas',
381+
UMarkdownUtils in 'UMarkdownUtils.pas',
382+
ActiveText.UMarkdownRenderer in 'ActiveText.UMarkdownRenderer.pas',
383+
UMarkdownSnippetDoc in 'UMarkdownSnippetDoc.pas';
381384

382385
// Include resources
383386
{$Resource ExternalObj.tlb} // Type library file

Src/CodeSnip.dproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,9 @@
584584
<DCCReference Include="USaveInfoMgr.pas"/>
585585
<DCCReference Include="ClassHelpers.RichEdit.pas"/>
586586
<DCCReference Include="UHTMLSnippetDoc.pas"/>
587+
<DCCReference Include="UMarkdownUtils.pas"/>
588+
<DCCReference Include="ActiveText.UMarkdownRenderer.pas"/>
589+
<DCCReference Include="UMarkdownSnippetDoc.pas"/>
587590
<None Include="CodeSnip.todo"/>
588591
<BuildConfiguration Include="Base">
589592
<Key>Base</Key>

Src/FrSourcePrefs.pas

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,14 @@ implementation
127127
sRTFFileDesc = 'Rich text';
128128
sPascalFileDesc = 'Pascal';
129129
sTextFileDesc = 'Plain text';
130+
sMarkdownFileDesc = 'Markdown';
130131

131132

132133
const
133134
// Maps source code file types to descriptions
134135
cFileDescs: array[TSourceFileType] of string = (
135-
sTextFileDesc, sPascalFileDesc, sHTML5FileDesc, sXHTMLFileDesc, sRTFFileDesc
136+
sTextFileDesc, sPascalFileDesc, sHTML5FileDesc, sXHTMLFileDesc,
137+
sRTFFileDesc, sMarkdownFileDesc
136138
);
137139

138140

Src/UMarkdownSnippetDoc.pas

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
{
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at https://mozilla.org/MPL/2.0/
5+
*
6+
* Copyright (C) 2025, Peter Johnson (gravatar.com/delphidabbler).
7+
*
8+
* Implements a class that renders a document that describes a snippet in
9+
* Markdown format.
10+
}
11+
12+
13+
unit UMarkdownSnippetDoc;
14+
15+
interface
16+
17+
uses
18+
// Delphi
19+
SysUtils,
20+
// Project
21+
ActiveText.UMain,
22+
Hiliter.UGlobals,
23+
UEncodings,
24+
UIStringList,
25+
USnippetDoc;
26+
27+
type
28+
/// <summary>Renders a document that describes a snippet in Markdown format.
29+
/// </summary>
30+
TMarkdownSnippetDoc = class sealed (TSnippetDoc)
31+
strict private
32+
var
33+
/// <summary>Object used to build Markdown source code document.
34+
/// </summary>
35+
fDocument: TStringBuilder;
36+
/// <summary>Flag indicating if the snippet has Pascal code.</summary>
37+
/// <remarks>When <c>False</c> plain text is assumed.</remarks>
38+
fIsPascal: Boolean;
39+
strict private
40+
/// <summary>Renders a Markdown paragraph with all given text emboldened.
41+
/// </summary>
42+
procedure RenderStrongPara(const AText: string);
43+
/// <summary>Renders the given active text as Markdown.</summary>
44+
function ActiveTextToMarkdown(ActiveText: IActiveText): string;
45+
strict protected
46+
/// <summary>Initialises the Markdown document.</summary>
47+
procedure InitialiseDoc; override;
48+
/// <summary>Adds the given heading (i.e. snippet name) to the document.
49+
/// Can be user defined or from main database.</summary>
50+
procedure RenderHeading(const Heading: string; const UserDefined: Boolean);
51+
override;
52+
/// <summary>Adds the given snippet description to the document.</summary>
53+
/// <remarks>Active text formatting is observed and styled to suit the
54+
/// document.</remarks>
55+
procedure RenderDescription(const Desc: IActiveText); override;
56+
/// <summary>Highlights the given source code and adds it to the document.
57+
/// </summary>
58+
procedure RenderSourceCode(const SourceCode: string); override;
59+
/// <summary>Adds the given title, followed by the given text, to the
60+
/// document.</summary>
61+
procedure RenderTitledText(const Title, Text: string); override;
62+
/// <summary>Adds a comma-separated list of text, preceded by the given
63+
/// title, to the document.</summary>
64+
procedure RenderTitledList(const Title: string; List: IStringList);
65+
override;
66+
/// <summary>Outputs the given compiler test info, preceded by the given
67+
/// heading.</summary>
68+
procedure RenderCompilerInfo(const Heading: string;
69+
const Info: TCompileDocInfoArray); override;
70+
/// <summary>Outputs the given message stating that there is no compiler
71+
/// test info, preceded by the given heading.</summary>
72+
procedure RenderNoCompilerInfo(const Heading, NoCompileTests: string);
73+
override;
74+
/// <summary>Adds the given extra information about the snippet to the
75+
/// document.</summary>
76+
/// <remarks>Active text formatting is observed and styled to suit the
77+
/// document.</remarks>
78+
procedure RenderExtra(const ExtraText: IActiveText); override;
79+
/// <summary>Adds the given information about a code snippets database to
80+
/// the document.</summary>
81+
procedure RenderDBInfo(const Text: string); override;
82+
/// <summary>Finalises the document and returns its content as encoded
83+
/// data.</summary>
84+
function FinaliseDoc: TEncodedData; override;
85+
public
86+
/// <summary>Constructs an object to render Markdown information.</summary>
87+
/// <param name="AIsPascal"><c>Boolean</c> [in] Flag indicating whether the
88+
/// snippet contains Pascal code.</param>
89+
constructor Create(const AIsPascal: Boolean);
90+
/// <summary>Destroys the object.</summary>
91+
destructor Destroy; override;
92+
end;
93+
94+
implementation
95+
96+
uses
97+
// Delphi
98+
UStrUtils,
99+
// Project
100+
ActiveText.UMarkdownRenderer,
101+
UMarkdownUtils;
102+
103+
{ TMarkdownSnippetDoc }
104+
105+
function TMarkdownSnippetDoc.ActiveTextToMarkdown(
106+
ActiveText: IActiveText): string;
107+
var
108+
Renderer: TActiveTextMarkdown;
109+
begin
110+
Renderer := TActiveTextMarkdown.Create;
111+
try
112+
Result := Renderer.Render(ActiveText);
113+
finally
114+
Renderer.Free;
115+
end;
116+
end;
117+
118+
constructor TMarkdownSnippetDoc.Create(const AIsPascal: Boolean);
119+
begin
120+
inherited Create;
121+
fDocument := TStringBuilder.Create;
122+
fIsPascal := AIsPascal;
123+
end;
124+
125+
destructor TMarkdownSnippetDoc.Destroy;
126+
begin
127+
fDocument.Free;
128+
inherited;
129+
end;
130+
131+
function TMarkdownSnippetDoc.FinaliseDoc: TEncodedData;
132+
begin
133+
Result := TEncodedData.Create(fDocument.ToString, etUnicode);
134+
end;
135+
136+
procedure TMarkdownSnippetDoc.InitialiseDoc;
137+
begin
138+
// Do nowt
139+
end;
140+
141+
procedure TMarkdownSnippetDoc.RenderCompilerInfo(const Heading: string;
142+
const Info: TCompileDocInfoArray);
143+
resourcestring
144+
sCompiler = 'Compiler';
145+
sResults = 'Results';
146+
var
147+
CompilerInfo: TCompileDocInfo; // info about each compiler
148+
begin
149+
RenderStrongPara(Heading);
150+
151+
fDocument.AppendLine(TMarkdown.TableHeading([sCompiler, sResults]));
152+
for CompilerInfo in Info do
153+
fDocument.AppendLine(
154+
TMarkdown.TableRow([CompilerInfo.Compiler, CompilerInfo.Result])
155+
);
156+
fDocument.AppendLine;
157+
end;
158+
159+
procedure TMarkdownSnippetDoc.RenderDBInfo(const Text: string);
160+
begin
161+
fDocument
162+
.AppendLine(TMarkdown.WeakEmphasis(TMarkdown.EscapeText(Text)))
163+
.AppendLine;
164+
end;
165+
166+
procedure TMarkdownSnippetDoc.RenderDescription(const Desc: IActiveText);
167+
var
168+
DescStr: string;
169+
begin
170+
DescStr := ActiveTextToMarkdown(Desc);
171+
if not StrIsEmpty(DescStr, True) then
172+
fDocument.AppendLine(DescStr);
173+
end;
174+
175+
procedure TMarkdownSnippetDoc.RenderExtra(const ExtraText: IActiveText);
176+
var
177+
ExtraStr: string;
178+
begin
179+
ExtraStr := ActiveTextToMarkdown(ExtraText);
180+
if not StrIsEmpty(ExtraStr, True) then
181+
fDocument.AppendLine(ExtraStr);
182+
end;
183+
184+
procedure TMarkdownSnippetDoc.RenderHeading(const Heading: string;
185+
const UserDefined: Boolean);
186+
begin
187+
fDocument
188+
.AppendLine(TMarkdown.Heading(TMarkdown.EscapeText(Heading), 1))
189+
.AppendLine;
190+
end;
191+
192+
procedure TMarkdownSnippetDoc.RenderNoCompilerInfo(const Heading,
193+
NoCompileTests: string);
194+
begin
195+
RenderStrongPara(Heading);
196+
fDocument
197+
.AppendLine(TMarkdown.Paragraph(TMarkdown.EscapeText(NoCompileTests)))
198+
.AppendLine;
199+
end;
200+
201+
procedure TMarkdownSnippetDoc.RenderSourceCode(const SourceCode: string);
202+
begin
203+
fDocument
204+
.AppendLine(
205+
TMarkdown.FencedCode(SourceCode, StrIf(fIsPascal, 'pascal', ''))
206+
)
207+
.AppendLine;
208+
end;
209+
210+
procedure TMarkdownSnippetDoc.RenderStrongPara(const AText: string);
211+
begin
212+
fDocument
213+
.AppendLine(
214+
TMarkdown.Paragraph(
215+
TMarkdown.StrongEmphasis(TMarkdown.EscapeText(AText))
216+
)
217+
)
218+
.AppendLine;
219+
end;
220+
221+
procedure TMarkdownSnippetDoc.RenderTitledList(const Title: string;
222+
List: IStringList);
223+
begin
224+
RenderTitledText(Title, CommaList(List));
225+
end;
226+
227+
procedure TMarkdownSnippetDoc.RenderTitledText(const Title, Text: string);
228+
begin
229+
RenderStrongPara(Title);
230+
fDocument
231+
.AppendLine(TMarkdown.Paragraph(TMarkdown.EscapeText(Text)))
232+
.AppendLine;
233+
end;
234+
235+
end.

0 commit comments

Comments
 (0)