@@ -120,14 +120,17 @@ TActiveTextAttrNames = record
120
120
type
121
121
// / <summary>Supported types of active text action elements.</summary>
122
122
TActiveTextActionElemKind = (
123
- ekLink, // link element: has a URL (inline)
124
- ekStrong, // text formatted as strong (inline)
125
- ekEm, // text formatted as emphasised (inline)
126
- ekVar, // text formatted as variable (inline)
127
- ekPara, // delimits a paragraph (block level)
128
- ekWarning, // text formatted as a warning (inline)
129
- ekHeading, // delimits a heading (block level)
130
- ekMono // text formatted as mono spaced (inline)
123
+ ekLink, // link element: has a URL (inline)
124
+ ekStrong, // text formatted as strong (inline)
125
+ ekEm, // text formatted as emphasised (inline)
126
+ ekVar, // text formatted as variable (inline)
127
+ ekPara, // delimits a paragraph (block level)
128
+ ekWarning, // text formatted as a warning (inline)
129
+ ekHeading, // delimits a heading (block level)
130
+ ekMono, // text formatted as mono spaced (inline)
131
+ ekUnorderedList, // container for unordered lists (block level)
132
+ ekOrderedList, // container for ordered list (block level)
133
+ ekListItem // list item (block level)
131
134
);
132
135
133
136
type
@@ -157,12 +160,6 @@ TActiveTextAttrNames = record
157
160
function GetAttrs : IActiveTextAttrs;
158
161
// / <summary>Object describing element's attributes.</summary>
159
162
property Attrs: IActiveTextAttrs read GetAttrs;
160
- // / <summary>Returns value that indicates whether element is an inline or
161
- // / block element.</summary>
162
- function GetDisplayStyle : TActiveTextDisplayStyle;
163
- // / <summary>Indicates whether element displays inline or as a block.
164
- // / </summary>
165
- property DisplayStyle: TActiveTextDisplayStyle read GetDisplayStyle;
166
163
end ;
167
164
168
165
type
@@ -273,6 +270,162 @@ TActiveTextFactory = class(TNoConstructObject)
273
270
IActiveTextAttrs; overload;
274
271
end ;
275
272
273
+ type
274
+ // / <summary>Provides information about the capabilities of each supported
275
+ // / active text element.</summary>
276
+ TActiveTextElemCaps = record
277
+ strict private
278
+ type
279
+ // / <summary>Fields used to define an active text element's capabilities.
280
+ // / </summary>
281
+ TCaps = record
282
+ public
283
+ var
284
+ // / <summary>Determines how element is to be displayed.</summary>
285
+ DisplayStyle: TActiveTextDisplayStyle;
286
+ // / <summary>Set of elements that may not occur inside the element.
287
+ // / </summary>
288
+ Exclusions: TActiveTextActionElemKinds;
289
+ // / <summary>Set of elements that are permitted as parents of the
290
+ // / element.</summary>
291
+ // / <remarks>An empty set is taken to mean any element is permitted.
292
+ // / </remarks>
293
+ RequiredParents: TActiveTextActionElemKinds;
294
+ // / <summary>Specifies whether plain text can be contained within the
295
+ // / element.</summary>
296
+ PermitsText: Boolean;
297
+ end ;
298
+ const
299
+ // / <summary>Set of block level elements.</summary>
300
+ BlockElems = [
301
+ ekPara, ekHeading, ekUnorderedList, ekOrderedList, ekListItem
302
+ ];
303
+ // / <summary>Set of inline elements.</summary>
304
+ InlineElems = [
305
+ ekLink, ekStrong, ekEm, ekVar, ekWarning, ekMono
306
+ ];
307
+ // / <summary>Set of all elements.</summary>
308
+ AllElems = BlockElems + InlineElems;
309
+ // / <summary>Map of all elements to their capabilities.</summary>
310
+ Map: array [TActiveTextActionElemKind] of TCaps =
311
+ (
312
+ (
313
+ // ekLink
314
+ // may contain any inline elements but no block elements
315
+ DisplayStyle: dsInline;
316
+ Exclusions: BlockElems;
317
+ RequiredParents: [];
318
+ PermitsText: True;
319
+ ),
320
+ (
321
+ // ekStrong
322
+ // may contain any inline elements but no block elements
323
+ DisplayStyle: dsInline;
324
+ Exclusions: BlockElems;
325
+ RequiredParents: [];
326
+ PermitsText: True;
327
+ ),
328
+ (
329
+ // ekEm
330
+ // may contain any inline elements but no block elements
331
+ DisplayStyle: dsInline;
332
+ Exclusions: BlockElems;
333
+ RequiredParents: [];
334
+ PermitsText: True;
335
+ ),
336
+ (
337
+ // ekVar
338
+ // may contain any inline elements but no block elements
339
+ DisplayStyle: dsInline;
340
+ Exclusions: BlockElems;
341
+ RequiredParents: [];
342
+ PermitsText: True;
343
+ ),
344
+ (
345
+ // ekPara
346
+ // may contain any inline elements but no block elements
347
+ DisplayStyle: dsBlock;
348
+ Exclusions: BlockElems;
349
+ RequiredParents: [];
350
+ PermitsText: True;
351
+ ),
352
+ (
353
+ // ekWarning
354
+ // may contain any inline elements but no block elements
355
+ DisplayStyle: dsInline;
356
+ Exclusions: BlockElems;
357
+ RequiredParents: [];
358
+ PermitsText: True;
359
+ ),
360
+ (
361
+ // ekHeading
362
+ // may contain any inline elements but no block elements
363
+ DisplayStyle: dsBlock;
364
+ Exclusions: BlockElems;
365
+ RequiredParents: [];
366
+ PermitsText: True;
367
+ ),
368
+ (
369
+ // ekMono
370
+ // may contain any inline elements but no block elements
371
+ DisplayStyle: dsInline;
372
+ Exclusions: BlockElems;
373
+ RequiredParents: [];
374
+ PermitsText: True;
375
+ ),
376
+ (
377
+ // ekUnorderedList
378
+ // may contain only list item elements
379
+ DisplayStyle: dsBlock;
380
+ Exclusions: AllElems - [ekListItem];
381
+ RequiredParents: [];
382
+ PermitsText: False
383
+ ),
384
+ (
385
+ // ekOrderedList
386
+ // may contain only list item elements
387
+ DisplayStyle: dsBlock;
388
+ Exclusions: AllElems - [ekListItem];
389
+ RequiredParents: [];
390
+ PermitsText: False;
391
+ ),
392
+ (
393
+ // ekListItem
394
+ // may contain any inline or block elements except another list
395
+ // item
396
+ DisplayStyle: dsBlock;
397
+ Exclusions: [ekListItem];
398
+ RequiredParents: [ekOrderedList, ekUnorderedList];
399
+ PermitsText: True;
400
+ )
401
+ );
402
+ public
403
+ // / <summary>Returns the display type of the given element.</summary>
404
+ class function DisplayStyleOf (const Elem: TActiveTextActionElemKind):
405
+ TActiveTextDisplayStyle; static;
406
+ // / <summary>Checks whether the given element can contain text.</summary>
407
+ class function CanContainText (const Elem: TActiveTextActionElemKind):
408
+ Boolean; static;
409
+ // / <summary>Checks whether the given Parent element can contain the given
410
+ // / Child element.</summary>
411
+ class function CanContainElem (
412
+ const Parent, Child: TActiveTextActionElemKind): Boolean; static;
413
+ // / <summary>Checks whether the given Parent element is required as a
414
+ // / parent of the given Child element.</summary>
415
+ class function IsRequiredParent (
416
+ const Parent, Child: TActiveTextActionElemKind): Boolean; static;
417
+ // / <summary>Checks whether the given element is permitted in the root of
418
+ // / an active text document, i.e. outside any other block level element.
419
+ // / </summary>
420
+ class function IsElemPermittedInRoot (const Elem: TActiveTextActionElemKind):
421
+ Boolean; static;
422
+ // / <summary>Checks whether the given child element is excluded from being
423
+ // / a child of the given parent element.</summary>
424
+ class function IsExcludedElem (
425
+ const Parent, Child: TActiveTextActionElemKind): Boolean; static;
426
+
427
+ end ;
428
+
276
429
277
430
implementation
278
431
@@ -354,7 +507,7 @@ TActiveTextTextElem = class(TInterfacedObject,
354
507
fText: string;
355
508
public
356
509
// / <summary>Object constructor. Records given element text and sets
357
- // / required kind for a text element.</summary>
510
+ // / required Elem for a text element.</summary>
358
511
constructor Create(const Text: string);
359
512
// / <summary>Assigns properties of another object to this object.</summary>
360
513
// / <param name="Src">IInterface [in] Object whose properties are to be
@@ -375,15 +528,15 @@ TActiveTextActionElem = class(TInterfacedObject,
375
528
IActiveTextElem, IActiveTextActionElem, IAssignable, IClonable
376
529
)
377
530
strict private
378
- // / <summary>Kind of element encapsulated by this object.</summary>
531
+ // / <summary>Elem of element encapsulated by this object.</summary>
379
532
fKind: TActiveTextActionElemKind;
380
533
// / <summary>State of element: opening or closing.</summary>
381
534
fState: TActiveTextElemState;
382
535
// / <summary>Attributes associated with element.</summary>
383
536
fAttrs: IActiveTextAttrs;
384
537
public
385
538
// / <summary>Object constructor. Creates an action element.</summary>
386
- // / <param name="AKind">TActiveTextElemKind [in] Required kind of element.
539
+ // / <param name="AKind">TActiveTextElemKind [in] Required Elem of element.
387
540
// / </param>
388
541
// / <param name="AAttrs">IActiveTextAttrs [in] Element's attributes.
389
542
// / </param>
@@ -402,7 +555,7 @@ TActiveTextActionElem = class(TInterfacedObject,
402
555
// / <summary>Returns a cloned instance of this object.</summary>
403
556
// / <remarks>Method of IClonable.</remarks>
404
557
function Clone : IInterface;
405
- // / <summary>Returns kind of action represented by this element.</summary>
558
+ // / <summary>Returns Elem of action represented by this element.</summary>
406
559
// / <remarks>Method of IActiveTextActionElem.</remarks>
407
560
function GetKind : TActiveTextActionElemKind;
408
561
// / <summary>Returns state of element.</summary>
@@ -411,10 +564,6 @@ TActiveTextActionElem = class(TInterfacedObject,
411
564
// / <summary>Returns object describing element's attributes.</summary>
412
565
// / <remarks>Method of IActiveTextActionElem.</remarks>
413
566
function GetAttrs : IActiveTextAttrs;
414
- // / <summary>Returns value that indicates whether element is an inline or
415
- // / block element.</summary>
416
- // / <remarks>Method of IActiveTextActionElem.</remarks>
417
- function GetDisplayStyle : TActiveTextDisplayStyle;
418
567
end ;
419
568
420
569
type
@@ -618,7 +767,7 @@ function TActiveText.ToString: string;
618
767
if Supports(Elem, IActiveTextTextElem, TextElem) then
619
768
SB.Append(TextElem.Text);
620
769
if Supports(Elem, IActiveTextActionElem, ActionElem)
621
- and (ActionElem.DisplayStyle = dsBlock)
770
+ and (TActiveTextElemCaps.DisplayStyleOf( ActionElem.Kind) = dsBlock)
622
771
and (ActionElem.State = fsClose) then
623
772
// new line at end of block to separate text at end of closing block
624
773
// from text at start of following block
@@ -689,14 +838,6 @@ function TActiveTextActionElem.GetAttrs: IActiveTextAttrs;
689
838
Result := fAttrs;
690
839
end ;
691
840
692
- function TActiveTextActionElem.GetDisplayStyle : TActiveTextDisplayStyle;
693
- begin
694
- if GetKind in [ekPara, ekHeading] then
695
- Result := dsBlock
696
- else
697
- Result := dsInline;
698
- end ;
699
-
700
841
function TActiveTextActionElem.GetKind : TActiveTextActionElemKind;
701
842
begin
702
843
Result := fKind;
@@ -756,5 +897,45 @@ function TActiveTextAttrs.GetEnumerator: TEnumerator<TPair<string, string>>;
756
897
Result := fMap.GetEnumerator;
757
898
end ;
758
899
900
+ { TActiveTextElemCapsMap }
901
+
902
+ class function TActiveTextElemCaps.CanContainElem (const Parent,
903
+ Child: TActiveTextActionElemKind): Boolean;
904
+ begin
905
+ Result := not (Child in Map[Parent].Exclusions);
906
+ end ;
907
+
908
+ class function TActiveTextElemCaps.CanContainText (
909
+ const Elem: TActiveTextActionElemKind): Boolean;
910
+ begin
911
+ Result := Map[Elem].PermitsText;
912
+ end ;
913
+
914
+ class function TActiveTextElemCaps.DisplayStyleOf (
915
+ const Elem: TActiveTextActionElemKind): TActiveTextDisplayStyle;
916
+ begin
917
+ Result := Map[Elem].DisplayStyle;
918
+ end ;
919
+
920
+ class function TActiveTextElemCaps.IsElemPermittedInRoot (
921
+ const Elem: TActiveTextActionElemKind): Boolean;
922
+ begin
923
+ Result := Map[Elem].RequiredParents = [];
924
+ end ;
925
+
926
+ class function TActiveTextElemCaps.IsExcludedElem (const Parent,
927
+ Child: TActiveTextActionElemKind): Boolean;
928
+ begin
929
+ Result := Child in Map[Parent].Exclusions;
930
+ end ;
931
+
932
+ class function TActiveTextElemCaps.IsRequiredParent (
933
+ const Parent, Child: TActiveTextActionElemKind): Boolean;
934
+ begin
935
+ if Map[Child].RequiredParents = [] then
936
+ Exit(True);
937
+ Result := Parent in Map[Child].RequiredParents;
938
+ end ;
939
+
759
940
end .
760
941
0 commit comments