@@ -47,43 +47,43 @@ TTagInfo = class(TObject)
47
47
TCSSStyles = class (TObject)
48
48
strict private
49
49
var
50
- fWrapperClass: string;
51
50
fElemClassMap: array [TActiveTextActionElemKind] of string;
52
51
procedure SetElemClass (ElemKind: TActiveTextActionElemKind;
53
52
const Value : string); inline;
54
53
function GetElemClass (ElemKind: TActiveTextActionElemKind): string;
55
54
inline;
56
55
public
57
56
constructor Create;
58
- property WrapperClass: string read fWrapperClass write fWrapperClass;
59
57
property ElemClasses[Kind: TActiveTextActionElemKind]: string
60
58
read GetElemClass write SetElemClass;
61
59
end ;
62
60
strict private
63
61
var
64
62
fCSSStyles: TCSSStyles;
65
63
fBuilder: TStringBuilder;
66
- fInBlock: Boolean ;
64
+ fLevel: Integer ;
67
65
fTagInfoMap: TTagInfoMap;
66
+ fIsStartOfTextLine: Boolean;
68
67
fLINestingDepth: Cardinal;
68
+ const
69
+ IndentMult = 2 ;
69
70
procedure InitialiseTagInfoMap ;
70
- procedure InitialiseRender ;
71
- procedure RenderTextElem (Elem: IActiveTextTextElem);
72
- procedure RenderBlockActionElem (Elem: IActiveTextActionElem);
73
- procedure RenderInlineActionElem (Elem: IActiveTextActionElem);
74
- procedure FinaliseRender ;
71
+ function RenderTag (const TagElem: IActiveTextActionElem): string;
72
+ function RenderText (const TextElem: IActiveTextTextElem): string;
75
73
function MakeOpeningTag (const Elem: IActiveTextActionElem): string;
76
74
function MakeClosingTag (const Elem: IActiveTextActionElem): string;
77
75
public
78
76
constructor Create;
79
77
destructor Destroy; override;
80
78
function Render (ActiveText: IActiveText): string;
81
- property Styles: TCSSStyles read fCSSStyles;
82
79
end ;
83
80
84
81
85
82
implementation
86
83
84
+ uses
85
+ UConsts, UIStringList, UStrUtils;
86
+
87
87
88
88
{ TActiveTextHTML }
89
89
@@ -107,22 +107,6 @@ destructor TActiveTextHTML.Destroy;
107
107
inherited ;
108
108
end ;
109
109
110
- procedure TActiveTextHTML.FinaliseRender ;
111
- begin
112
- fBuilder.AppendLine(THTML.ClosingTag(' div' ));
113
- end ;
114
-
115
- procedure TActiveTextHTML.InitialiseRender ;
116
- var
117
- WrapperClassAttr: IHTMLAttributes;
118
- begin
119
- if fCSSStyles.WrapperClass <> ' ' then
120
- WrapperClassAttr := THTMLAttributes.Create(' class' , fCSSStyles.WrapperClass)
121
- else
122
- WrapperClassAttr := nil ;
123
- fBuilder.AppendLine(THTML.OpeningTag(' div' , WrapperClassAttr));
124
- end ;
125
-
126
110
procedure TActiveTextHTML.InitialiseTagInfoMap ;
127
111
var
128
112
NullAttrs: TTagInfo.TTagAttrCallback;
@@ -131,7 +115,10 @@ procedure TActiveTextHTML.InitialiseTagInfoMap;
131
115
ElemKind: TActiveTextActionElemKind;
132
116
const
133
117
Tags: array [TActiveTextActionElemKind] of string = (
134
- ' a' , ' strong' , ' em' , ' var' , ' p' , ' span' , ' h2' , ' code' , ' ul' , ' ol' , ' li'
118
+ ' a' { ekLink} , ' strong' { ekStrong} , ' em' { ekEm} , ' var' { ekVar} , ' p' { ekPara} ,
119
+ ' span' { ekWarning} , ' h2' { ekHeading} , ' code' { ekMono} ,
120
+ ' ul' { ekUnorderedList} , ' ol' { ekUnorderedList} , ' li' { ekListItem} ,
121
+ ' div' { ekBlock} , ' div' { ekDocument}
135
122
);
136
123
begin
137
124
NullAttrs := function(Elem: IActiveTextActionElem): IHTMLAttributes
@@ -178,80 +165,100 @@ function TActiveTextHTML.MakeOpeningTag(const Elem: IActiveTextActionElem):
178
165
179
166
function TActiveTextHTML.Render (ActiveText: IActiveText): string;
180
167
var
181
- Elem: IActiveTextElem;
182
- TextElem: IActiveTextTextElem;
183
- ActionElem: IActiveTextActionElem;
168
+ Elem: IActiveTextElem; // each element in active text object
169
+ TextElem: IActiveTextTextElem; // an active text text element
170
+ TagElem: IActiveTextActionElem; // an active text action element
171
+ Text: string;
172
+ SrcLines: IStringList;
173
+ SrcLine: string;
174
+ DestLines: IStringList;
175
+ DestLine: string;
184
176
begin
185
- fBuilder.Clear;
186
- fInBlock := False;
187
- InitialiseRender;
177
+ if ActiveText.IsEmpty then
178
+ Exit(' ' );
179
+ Text := ' ' ;
180
+ fLevel := 0 ;
188
181
for Elem in ActiveText do
189
182
begin
190
183
if Supports(Elem, IActiveTextTextElem, TextElem) then
191
- RenderTextElem(TextElem)
192
- else if Supports(Elem, IActiveTextActionElem, ActionElem) then
193
- begin
194
- if TActiveTextElemCaps.DisplayStyleOf(ActionElem.Kind) = dsBlock then
195
- RenderBlockActionElem(ActionElem)
196
- else
197
- RenderInlineActionElem(ActionElem);
198
- end ;
184
+ Text := Text + RenderText(TextElem)
185
+ else if Supports(Elem, IActiveTextActionElem, TagElem) then
186
+ Text := Text + RenderTag(TagElem);
199
187
end ;
200
- FinaliseRender;
201
- Result := fBuilder.ToString;
188
+ SrcLines := TIStringList.Create(Text, EOL, False);
189
+ DestLines := TIStringList.Create;
190
+ for SrcLine in SrcLines do
191
+ begin
192
+ DestLine := StrTrimRight(SrcLine);
193
+ if not StrIsEmpty(DestLine) then
194
+ DestLines.Add(DestLine);
195
+ end ;
196
+ Result := DestLines.GetText(EOL, False);
202
197
end ;
203
198
204
- procedure TActiveTextHTML.RenderBlockActionElem (Elem: IActiveTextActionElem);
199
+ function TActiveTextHTML.RenderTag (const TagElem: IActiveTextActionElem):
200
+ string;
205
201
begin
206
- case Elem.State of
207
- fsOpen:
208
- begin
209
- if Elem.Kind = ekListItem then
210
- Inc(fLINestingDepth);
211
- fBuilder.Append(MakeOpeningTag(Elem));
212
- fInBlock := True;
213
- end ;
202
+ Result := ' ' ;
203
+ case TagElem.State of
214
204
fsClose:
215
205
begin
216
- fInBlock := False;
217
- fBuilder.AppendLine(MakeClosingTag(Elem));
218
- if Elem.Kind = ekListItem then
219
- Dec(fLINestingDepth);
206
+ Result := MakeClosingTag(TagElem);
207
+ if TActiveTextElemCaps.DisplayStyleOf(TagElem.Kind) = dsBlock then
208
+ begin
209
+ Dec(fLevel);
210
+ Result := EOL + StrOfSpaces(IndentMult * fLevel) + Result + EOL;
211
+ fIsStartOfTextLine := True;
212
+ end ;
220
213
end ;
221
- end ;
222
- end ;
223
-
224
- procedure TActiveTextHTML.RenderInlineActionElem (Elem: IActiveTextActionElem);
225
- begin
226
- if not fInBlock and (fLINestingDepth = 0 ) then
227
- Exit;
228
- case Elem.State of
229
214
fsOpen:
230
- fBuilder.Append(MakeOpeningTag(Elem));
231
- fsClose:
232
- fBuilder.Append(MakeClosingTag(Elem));
215
+ begin
216
+ Result := MakeOpeningTag(TagElem);
217
+ if TActiveTextElemCaps.DisplayStyleOf(TagElem.Kind) = dsBlock then
218
+ begin
219
+ Result := EOL + StrOfSpaces(IndentMult * fLevel) + Result + EOL;
220
+ Inc(fLevel);
221
+ fIsStartOfTextLine := True;
222
+ end
223
+ else if TActiveTextElemCaps.DisplayStyleOf(TagElem.Kind) = dsInline then
224
+ begin
225
+ if fIsStartOfTextLine then
226
+ begin
227
+ Result := StrOfSpaces(IndentMult * fLevel) + Result;
228
+ fIsStartOfTextLine := False;
229
+ end ;
230
+ end ;
231
+ end ;
233
232
end ;
234
233
end ;
235
234
236
- procedure TActiveTextHTML.RenderTextElem (Elem: IActiveTextTextElem);
235
+ function TActiveTextHTML.RenderText (const TextElem: IActiveTextTextElem):
236
+ string;
237
237
begin
238
- if not fInBlock and (fLINestingDepth = 0 ) then
239
- Exit;
240
- fBuilder.Append(THTML.Entities(Elem.Text));
238
+ if fIsStartOfTextLine then
239
+ begin
240
+ Result := StrOfSpaces(IndentMult * fLevel);
241
+ fIsStartOfTextLine := False;
242
+ end
243
+ else
244
+ Result := ' ' ;
245
+ Result := Result + THTML.Entities(TextElem.Text);
241
246
end ;
242
247
243
248
{ TActiveTextHTML.TCSSStyles }
244
249
245
250
constructor TActiveTextHTML.TCSSStyles.Create;
246
251
const
247
252
DefaultClasses: array [TActiveTextActionElemKind] of string = (
248
- ' external-link' , ' ' , ' ' , ' ' , ' ' , ' warning' , ' ' , ' ' , ' ' , ' ' , ' '
253
+ ' external-link' { ekLink} , ' ' { ekStrong} , ' ' { ekEm} , ' ' { ekVar} , ' ' { ekPara} ,
254
+ ' warning' { ekWarning} , ' ' { ekHeading} , ' ' { ekMono} , ' ' { ekUnorderedList} ,
255
+ ' ' { ekOrderedList} , ' ' { ekListItem} , ' ' { ekBlock} ,
256
+ ' active-text' { ekDocument}
249
257
);
250
258
var
251
259
ElemKind: TActiveTextActionElemKind;
252
260
begin
253
261
inherited Create;
254
- fWrapperClass := ' active-text' ;
255
262
for ElemKind := Low(TActiveTextActionElemKind)
256
263
to High(TActiveTextActionElemKind) do
257
264
SetElemClass(ElemKind, DefaultClasses[ElemKind]);
0 commit comments