diff --git a/HtmlParserEx.pas b/HtmlParserEx.pas index d4474b9..0781479 100644 --- a/HtmlParserEx.pas +++ b/HtmlParserEx.pas @@ -10,13 +10,14 @@ interface System.SysUtils, System.Classes, System.Generics.Collections - {$IFDEF UseXPath} - ,System.RegularExpressionsCore - {$ENDIF}; +{$IFDEF UseXPath} + , System.RegularExpressionsCore +{$ENDIF}; {$IF (defined(IOS) and defined(CPUARM)) or defined(ANDROID)} {$DEFINE MOBILE_DEV} {$ENDIF} + const // By design each IHtmlElement has a TagName property, even it's a 'Text' element. // so cSpecialTagName_Text represents the fake tag name of a Text element @@ -26,94 +27,99 @@ interface type IHtmlElement = interface; IHtmlElementList = interface; - TElementEachEvent = reference to procedure(AIndex:Integer; AEl:IHtmlElement); + TElementEachEvent = reference to procedure(AIndex: Integer; + AEl: IHtmlElement); + TStringDictionary = TDictionary; IHtmlElement = interface ['{8C75239C-8CFA-499F-B115-7CEBEDFB421B}'] - function GetParent:IHtmlElement; stdcall; - function GetTagName:String; stdcall; - procedure SetTagName(Value:String); stdcall; - function GetContent:String; stdcall; - function GetOrignal:String; stdcall; - function GetChildrenCount:Integer; stdcall; - function GetChildren(Index:Integer):IHtmlElement; stdcall; - function GetCloseTag:IHtmlElement; stdcall; - function GetInnerHtml():String; stdcall; - function GetOuterHtml():String; stdcall; - function GetInnerText():String; stdcall; - procedure SetInnerText(Value:String); stdcall; - function GetAttributes(Key:String):String; stdcall; - procedure SetAttributes(Key:String; Value:String); stdcall; - procedure RemoveAttr(AAttrName:string); stdcall; - function GetSourceLineNum():Integer; stdcall; - function GetSourceColNum():Integer; stdcall; + function GetParent: IHtmlElement; stdcall; + function GetTagName: String; stdcall; + procedure SetTagName(Value: String); stdcall; + function GetContent: String; stdcall; + function GetOrignal: String; stdcall; + function GetChildrenCount: Integer; stdcall; + function GetChildren(Index: Integer): IHtmlElement; overload; stdcall; + function GetChildren: IHtmlElementList; overload; stdcall; + function GetCloseTag: IHtmlElement; stdcall; + function GetInnerHtml(): String; stdcall; + function GetOuterHtml(): String; stdcall; + function GetInnerText(): String; stdcall; + procedure SetInnerText(Value: String); stdcall; + function GetAttributes(Key: String): String; overload; stdcall; + function GetAttributes: TStringDictionary; overload; stdcall; + procedure SetAttributes(Key: String; Value: String); stdcall; + procedure RemoveAttr(AAttrName: string); stdcall; + function GetSourceLineNum(): Integer; stdcall; + function GetSourceColNum(): Integer; stdcall; // Add and remove nodes - function RemoveChild(ANode:IHtmlElement):Integer; stdcall; + function RemoveChild(ANode: IHtmlElement): Integer; stdcall; procedure Remove; stdcall; - function AppedChild(const ATag:string):IHtmlElement; stdcall; + function AppedChild(const ATag: string): IHtmlElement; stdcall; // Does the property exist - function HasAttribute(AttributeName:String):Boolean; stdcall; + function HasAttribute(AttributeName: String): Boolean; stdcall; { Find Element using CSS selector syntax, "pseudo-class" is not supported http://www.w3.org/TR/CSS2/selector.html } - function SimpleCSSSelector(const selector:String):IHtmlElementList; stdcall; - function Find(const selector:String):IHtmlElementList; stdcall; - {$IFDEF UseXPath} - function FindX(const AXPath:String):IHtmlElementList; stdcall; - {$ENDIF} + function SimpleCSSSelector(const selector: String) + : IHtmlElementList; stdcall; + function Find(const selector: String): IHtmlElementList; stdcall; +{$IFDEF UseXPath} + function FindX(const AXPath: String): IHtmlElementList; stdcall; +{$ENDIF} // enum property - function EnumAttributeNames(Index:Integer):String; stdcall; - property TagName:String read GetTagName write SetTagName; - property ChildrenCount:Integer read GetChildrenCount; - property Children[index:Integer]:IHtmlElement read GetChildren; default; - property CloseTag:IHtmlElement read GetCloseTag; - property Content:String read GetContent; - property Orignal:String read GetOrignal; - property Parent:IHtmlElement read GetParent; + function EnumAttributeNames(Index: Integer): String; stdcall; + property TagName: String read GetTagName write SetTagName; + property ChildrenCount: Integer read GetChildrenCount; + property Children[index: Integer]: IHtmlElement read GetChildren; default; + property CloseTag: IHtmlElement read GetCloseTag; + property Content: String read GetContent; + property Orignal: String read GetOrignal; + property Parent: IHtmlElement read GetParent; // Get the position of an element in the source code - property SourceLineNum:Integer read GetSourceLineNum; - property SourceColNum:Integer read GetSourceColNum; + property SourceLineNum: Integer read GetSourceLineNum; + property SourceColNum: Integer read GetSourceColNum; // - property InnerHtml:String read GetInnerHtml; - property OuterHtml:String read GetOuterHtml; - property InnerText:String read GetInnerText write SetInnerText; - property Text:String read GetInnerText write SetInnerText; - property Attributes[Key:String]:String read GetAttributes write SetAttributes; + property InnerHtml: String read GetInnerHtml; + property OuterHtml: String read GetOuterHtml; + property InnerText: String read GetInnerText write SetInnerText; + property Text: String read GetInnerText write SetInnerText; + property Attributes[Key: String]: String read GetAttributes + write SetAttributes; + property Attributes: TStringDictionary read GetAttributes; + property Children: IHTMLElementList read GetChildren; // ying32 does not change the original, just simplifies the use - property Attrs[Key:String]:String read GetAttributes write SetAttributes; + property Attrs[Key: String]: String read GetAttributes write SetAttributes; end; - THtmlListEnumerator = class private - FIndex:Integer; - FList:IHtmlElementList; + FIndex: Integer; + FList: IHtmlElementList; public - constructor Create(AList:IHtmlElementList); - function GetCurrent:IHtmlElement; inline; - function MoveNext:Boolean; - property Current:IHtmlElement read GetCurrent; + constructor Create(AList: IHtmlElementList); + function GetCurrent: IHtmlElement; inline; + function MoveNext: Boolean; + property Current: IHtmlElement read GetCurrent; end; - IHtmlElementList = interface ['{8E1380C6-4263-4BF6-8D10-091A86D8E7D9}'] - function GetCount:Integer; stdcall; - function GetItems(Index:Integer):IHtmlElement; stdcall; + function GetCount: Integer; stdcall; + function GetItems(Index: Integer): IHtmlElement; stdcall; procedure RemoveAll; stdcall; - procedure Remove(ANode:IHtmlElement); stdcall; - procedure Each(f:TElementEachEvent); stdcall; - function GetText:String; stdcall; - function GetEnumerator:THtmlListEnumerator; - property Text:String read GetText; - property Count:Integer read GetCount; - property Items[index:Integer]:IHtmlElement read GetItems; default; + procedure Remove(ANode: IHtmlElement); stdcall; + procedure Each(f: TElementEachEvent); stdcall; + function GetText: String; stdcall; + function GetEnumerator: THtmlListEnumerator; + property Text: String read GetText; + property Count: Integer read GetCount; + property Items[index: Integer]: IHtmlElement read GetItems; default; end; - -function ParserHTML(const Source:String):IHtmlElement; stdcall; -function DecodeHtmlEntities(S:string):string; forward; +function ParserHTML(const Source: String): IHtmlElement; stdcall; +function DecodeHtmlEntities(S: string): string; forward; implementation @@ -121,9 +127,9 @@ implementation StrUtils; type - TStringDictionary = TDictionary; TPropDictionary = TDictionary; TStringDynArray = TArray; + const WhiteSpace = [' ', #13, #10, #9]; // CSS Attribute Compare Operator @@ -138,184 +144,181 @@ implementation tpInlineOrEmpty = tpInline or tpEmpty; type - TAttrOperator = (aoExist, aoEqual, aoNotEqual, aoIncludeWord, aoBeginWord, aoBegin, aoEnd, aoContain); + TAttrOperator = (aoExist, aoEqual, aoNotEqual, aoIncludeWord, aoBeginWord, + aoBegin, aoEnd, aoContain); PAttrSelectorItem = ^TAttrSelectorItem; - TAttrSelectorItem = record - Key:string; - AttrOperator:TAttrOperator; - Value:string; + Key: string; + AttrOperator: TAttrOperator; + Value: string; end; - - TSelectorItemRelation = (sirNONE, sirDescendant, sirChildren, sirYoungerBrother, sirAllYoungerBrother); + TSelectorItemRelation = (sirNONE, sirDescendant, sirChildren, + sirYoungerBrother, sirAllYoungerBrother); PCSSSelectorItem = ^TCSSSelectorItem; - TCSSSelectorItem = record - Relation:TSelectorItemRelation; - szTag:string; + Relation: TSelectorItemRelation; + szTag: string; Attributes: array of TAttrSelectorItem; end; - TCSSSelectorItems = array of TCSSSelectorItem; PCSSSelectorItems = ^TCSSSelectorItems; TCSSSelectorItemGroup = array of TCSSSelectorItems; - // TSourceContext = record private - function GetCharOfCurrent(Index:Integer):Char; inline; - function PassedEndOfSourceCode:Boolean; inline; + function GetCharOfCurrent(Index: Integer): Char; inline; + function PassedEndOfSourceCode: Boolean; inline; public - SourceCode:string; - CharIndex:Integer; - LineNum:Integer; - ColNum:Integer; - CurrentChar:Char; - {$IFDEF DEBUG} - currentCode:PChar; - {$ENDIF} + SourceCode: string; + CharIndex: Integer; + LineNum: Integer; + ColNum: Integer; + CurrentChar: Char; +{$IFDEF DEBUG} + currentCode: PChar; +{$ENDIF} // Jump to the next char and return true if not exceeding the end of SourceCode - function JumpToNextChar:Boolean; overload; inline; + function JumpToNextChar: Boolean; overload; inline; // Jump multiple characters, and return the jumped steps - function JumpToNextChar(Step:Integer):Integer; overload; inline; - procedure setCode(const ACode:string); inline; - function ReadStr(UntilChars:TSysCharSet):string; inline; - function PeekStr(Index:Integer):string; overload; inline; - function PeekStr():string; overload; inline; - function subStr(Index, Count:Integer):string; overload; inline; - function subStr(Count:Integer):string; overload; inline; + function JumpToNextChar(Step: Integer): Integer; overload; inline; + procedure setCode(const ACode: string); inline; + function ReadStr(UntilChars: TSysCharSet): string; inline; + function PeekStr(Index: Integer): string; overload; inline; + function PeekStr(): string; overload; inline; + function subStr(Index, Count: Integer): string; overload; inline; + function subStr(Count: Integer): string; overload; inline; procedure SkipBlank(); inline; - property charOfCurrent[index:Integer]:Char read GetCharOfCurrent; + property charOfCurrent[index: Integer]: Char read GetCharOfCurrent; end; - TAttributeItem = record - Key, Value:string; + Key, Value: string; end; - TAttributeDynArray = TArray; TIHtmlElementList = class; THtmlElement = class; THtmlElementList = TList; - THtmlElement = class(TInterfacedObject, IHtmlElement) - private - function GetChildrens:IHtmlElementList; protected // ying32 - function GetParent:IHtmlElement; stdcall; - function GetTagName:String; stdcall; - procedure SetTagName(Value:String); stdcall; - function GetContent:String; stdcall; - function GetOrignal:String; stdcall; - function GetChildrenCount:Integer; stdcall; - function GetChildren(Index:Integer):IHtmlElement; stdcall; - function GetCloseTag:IHtmlElement; stdcall; - function GetInnerHtml():String; stdcall; - function GetOuterHtml():String; stdcall; - function GetInnerText():String; stdcall; - procedure SetInnerText(Value:String); stdcall; - function GetAttributes(Key:String):String; stdcall; - procedure SetAttributes(Key:String; Value:String); stdcall; - procedure RemoveAttr(AAttrName:string); stdcall; - function GetSourceLineNum():Integer; stdcall; - function GetSourceColNum():Integer; stdcall; + function GetParent: IHtmlElement; stdcall; + function GetTagName: String; stdcall; + procedure SetTagName(Value: String); stdcall; + function GetContent: String; stdcall; + function GetOrignal: String; stdcall; + function GetChildrenCount: Integer; stdcall; + function GetChildren(Index: Integer): IHtmlElement; overload; stdcall; + function GetChildren: IHtmlElementList; overload; stdcall; + function GetCloseTag: IHtmlElement; stdcall; + function GetInnerHtml(): String; stdcall; + function GetOuterHtml(): String; stdcall; + function GetInnerText(): String; stdcall; + procedure SetInnerText(Value: String); stdcall; + function GetAttributes(Key: String): String; overload; stdcall; + function GetAttributes: TStringDictionary; overload; stdcall; + procedure SetAttributes(Key: String; Value: String); stdcall; + procedure RemoveAttr(AAttrName: string); stdcall; + function GetSourceLineNum(): Integer; stdcall; + function GetSourceColNum(): Integer; stdcall; // ying32Added - function RemoveChild(ANode:IHtmlElement):Integer; stdcall; + function RemoveChild(ANode: IHtmlElement): Integer; stdcall; procedure Remove; stdcall; - function AppedChild(const ATag:string):IHtmlElement; stdcall; + function AppedChild(const ATag: string): IHtmlElement; stdcall; // Does the property exist - function HasAttribute(AttributeName:String):Boolean; stdcall; + function HasAttribute(AttributeName: String): Boolean; stdcall; { Find Element with CSS selector syntax, does not support "pseudo-class" http://www.w3.org/TR/CSS2/selector.html } - function SimpleCSSSelector(const selector:String):IHtmlElementList; stdcall; - function Find(const selector:String):IHtmlElementList; stdcall; - {$IFDEF UseXPath} - function FindX(const AXPath:String):IHtmlElementList; stdcall; - {$ENDIF} + function SimpleCSSSelector(const selector: String) + : IHtmlElementList; stdcall; + function Find(const selector: String): IHtmlElementList; stdcall; +{$IFDEF UseXPath} + function FindX(const AXPath: String): IHtmlElementList; stdcall; +{$ENDIF} // enum property - function EnumAttributeNames(Index:Integer):String; stdcall; - property TagName:String read GetTagName write SetTagName; - property ChildrenCount:Integer read GetChildrenCount; - property Children[index:Integer]:IHtmlElement read GetChildren; default; - property CloseTag:IHtmlElement read GetCloseTag; - property Content:String read GetContent; - property Orignal:String read GetOrignal; - property Parent:IHtmlElement read GetParent; + function EnumAttributeNames(Index: Integer): String; stdcall; + property TagName: String read GetTagName write SetTagName; + property ChildrenCount: Integer read GetChildrenCount; + property Children[index: Integer]: IHtmlElement read GetChildren; default; + property CloseTag: IHtmlElement read GetCloseTag; + property Content: String read GetContent; + property Orignal: String read GetOrignal; + property Parent: IHtmlElement read GetParent; // Get the position of an element in the source code - property SourceLineNum:Integer read GetSourceLineNum; - property SourceColNum:Integer read GetSourceColNum; + property SourceLineNum: Integer read GetSourceLineNum; + property SourceColNum: Integer read GetSourceColNum; // - property InnerHtml:String read GetInnerHtml; - property OuterHtml:String read GetOuterHtml; - property InnerText:String read GetInnerText; - property Attributes[Key:String]:String read GetAttributes write SetAttributes; - property Childrens:IHtmlElementList read GetChildrens; + property InnerHtml: String read GetInnerHtml; + property OuterHtml: String read GetOuterHtml; + property InnerText: String read GetInnerText; + property Attributes[Key: String]: String read GetAttributes + write SetAttributes; private - FClosed:Boolean; + FClosed: Boolean; // - FOwner:THtmlElement; - FCloseTag:IHtmlElement; - FTagName:string; - FIsCloseTag:Boolean; - FContent:string; - FOrignal:string; - FSourceLine:Integer; - FSourceCol:Integer; + FOwner: THtmlElement; + FCloseTag: IHtmlElement; + FTagName: string; + FIsCloseTag: Boolean; + FContent: string; + FOrignal: string; + FSourceLine: Integer; + FSourceCol: Integer; // - FAttributes:TStringDictionary; - FChildren:TIHtmlElementList; - procedure _GetHtml(IncludeSelf:Boolean; Sb:TStringBuilder); - procedure _GetText(IncludeSelf:Boolean; Sb:TStringBuilder); - procedure _SimpleCSSSelector(const ItemGroup:TCSSSelectorItemGroup; r:TIHtmlElementList); - procedure _Select(Item:PCSSSelectorItem; Count:Integer; r:TIHtmlElementList; OnlyTopLevel:Boolean = false); + FAttributes: TStringDictionary; + FChildren: TIHtmlElementList; + procedure _GetHtml(IncludeSelf: Boolean; Sb: TStringBuilder); + procedure _GetText(IncludeSelf: Boolean; Sb: TStringBuilder); + procedure _SimpleCSSSelector(const ItemGroup: TCSSSelectorItemGroup; + r: TIHtmlElementList); + procedure _Select(Item: PCSSSelectorItem; Count: Integer; + r: TIHtmlElementList; OnlyTopLevel: Boolean = false); public - constructor Create(AOwner:THtmlElement; AText:string; ALine, ACol:Integer); + constructor Create(AOwner: THtmlElement; AText: string; + ALine, ACol: Integer); destructor Destroy; override; end; - TIHtmlElementList = class(TInterfacedObject, IHtmlElementList) private // IHtmlElementList - function GetItems(Index:Integer):IHtmlElement; stdcall; - function GetCount:Integer; stdcall; + function GetItems(Index: Integer): IHtmlElement; stdcall; + function GetCount: Integer; stdcall; protected - FList:TList; - procedure SetItems(Index:Integer; const Value:IHtmlElement); inline; - function Add(Value:IHtmlElement):Integer; inline; - procedure Delete(Index:Integer); inline; + FList: TList; + procedure SetItems(Index: Integer; const Value: IHtmlElement); inline; + function Add(Value: IHtmlElement): Integer; inline; + procedure Delete(Index: Integer); inline; procedure Clear; inline; // ying32Added procedure RemoveAll; stdcall; - procedure Remove(ANode:IHtmlElement); stdcall; - procedure Each(f:TElementEachEvent); stdcall; - function GetText:String; stdcall; + procedure Remove(ANode: IHtmlElement); stdcall; + procedure Each(f: TElementEachEvent); stdcall; + function GetText: String; stdcall; public constructor Create; destructor Destroy; override; - function GetEnumerator:THtmlListEnumerator; - function IndexOf(Item:IHtmlElement):Integer; + function GetEnumerator: THtmlListEnumerator; + function IndexOf(Item: IHtmlElement): Integer; // IHtmlElementList - property Items[index:Integer]:IHtmlElement read GetItems write SetItems; default; - property Count:Integer read GetCount; + property Items[index: Integer]: IHtmlElement read GetItems + write SetItems; default; + property Count: Integer read GetCount; end; - -function SplitStr(ACharSet:TSysCharSet; AStr:string):TStringDynArray; +function SplitStr(ACharSet: TSysCharSet; AStr: string): TStringDynArray; var - L, I:Integer; - S:string; - StrChar:Char; + L, I: Integer; + S: string; + StrChar: Char; begin Result := nil; if Length(AStr) <= 0 then @@ -352,10 +355,9 @@ function SplitStr(ACharSet:TSysCharSet; AStr:string):TStringDynArray; end; end; - -function StrRight(const Value:string; Count:Integer):string; +function StrRight(const Value: string; Count: Integer): string; var - start:Integer; + start: Integer; begin start := Length(Value) - Count + 1; if start <= 0 then @@ -364,36 +366,34 @@ function StrRight(const Value:string; Count:Integer):string; Result := Copy(Value, start, Count); end; - -function StrLeft(const Value:string; Count:Integer):string; +function StrLeft(const Value: string; Count: Integer): string; begin Result := Copy(Value, LowStrIndex, Count); end; - // ComapreAttr -function _aoExist(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; +function _aoExist(const Item: TAttrSelectorItem; E: THtmlElement): Boolean; begin Result := E.FAttributes.ContainsKey(Item.Key); end; - -function _aoEqual(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; +function _aoEqual(const Item: TAttrSelectorItem; E: THtmlElement): Boolean; begin - Result := E.FAttributes.ContainsKey(Item.Key) and (E.FAttributes[Item.Key] = Item.Value); + Result := E.FAttributes.ContainsKey(Item.Key) and + (E.FAttributes[Item.Key] = Item.Value); end; - -function _aoNotEqual(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; +function _aoNotEqual(const Item: TAttrSelectorItem; E: THtmlElement): Boolean; begin - Result := E.FAttributes.ContainsKey(Item.Key) and (E.FAttributes[Item.Key] <> Item.Value); + Result := E.FAttributes.ContainsKey(Item.Key) and + (E.FAttributes[Item.Key] <> Item.Value); end; - -function _aoIncludeWord(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; +function _aoIncludeWord(const Item: TAttrSelectorItem; E: THtmlElement) + : Boolean; var - S:TStringDynArray; - I:Integer; + S: TStringDynArray; + I: Integer; begin Result := false; if not E.FAttributes.ContainsKey(Item.Key) then @@ -406,10 +406,9 @@ function _aoIncludeWord(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; Result := false; end; - -function _aoBeginWord(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; +function _aoBeginWord(const Item: TAttrSelectorItem; E: THtmlElement): Boolean; var - S:TStringDynArray; + S: TStringDynArray; begin Result := false; if not E.FAttributes.ContainsKey(Item.Key) then @@ -418,34 +417,33 @@ function _aoBeginWord(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; Result := (Length(S) > 0) and (S[0] = Item.Value); end; - -function _aoBegin(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; +function _aoBegin(const Item: TAttrSelectorItem; E: THtmlElement): Boolean; var - attr, Value:string; + attr, Value: string; begin Result := false; if not E.FAttributes.ContainsKey(Item.Key) then Exit; attr := E.FAttributes[Item.Key]; Value := Item.Value; - Result := (Length(attr) > Length(Value)) and (StrLeft(attr, Length(Value)) = Value); + Result := (Length(attr) > Length(Value)) and + (StrLeft(attr, Length(Value)) = Value); end; - -function _aoEnd(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; +function _aoEnd(const Item: TAttrSelectorItem; E: THtmlElement): Boolean; var - attr, Value:string; + attr, Value: string; begin Result := false; if not E.FAttributes.ContainsKey(Item.Key) then Exit; attr := E.FAttributes[Item.Key]; Value := Item.Value; - Result := (Length(attr) > Length(Value)) and (StrRight(attr, Length(Value)) = Value); + Result := (Length(attr) > Length(Value)) and + (StrRight(attr, Length(Value)) = Value); end; - -function _aoContain(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; +function _aoContain(const Item: TAttrSelectorItem; E: THtmlElement): Boolean; begin Result := false; if not E.FAttributes.ContainsKey(Item.Key) then @@ -454,21 +452,23 @@ function _aoContain(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; end; type - TFNCompareAttr = function(const Item:TAttrSelectorItem; E:THtmlElement):Boolean; -const - AttrCompareFuns: array [TAttrOperator] of TFNCompareAttr = (_aoExist, _aoEqual, _aoNotEqual, _aoIncludeWord, _aoBeginWord, _aoBegin, _aoEnd, _aoContain); -function GetTagProperty(const TagName:string):WORD; forward; + TFNCompareAttr = function(const Item: TAttrSelectorItem; + E: THtmlElement): Boolean; +const + AttrCompareFuns: array [TAttrOperator] of TFNCompareAttr = (_aoExist, + _aoEqual, _aoNotEqual, _aoIncludeWord, _aoBeginWord, _aoBegin, _aoEnd, + _aoContain); +function GetTagProperty(const TagName: string): WORD; forward; -procedure DoError(const Msg:string); +procedure DoError(const Msg: string); begin raise Exception.Create(Msg); end; - -procedure _ParserAttrs(var sc:TSourceContext; var Attrs:TAttributeDynArray); +procedure _ParserAttrs(var sc: TSourceContext; var Attrs: TAttributeDynArray); var - Item:TAttributeItem; + Item: TAttributeItem; begin SetLength(Attrs, 0); while True do @@ -490,10 +490,10 @@ procedure _ParserAttrs(var sc:TSourceContext; var Attrs:TAttributeDynArray); end; end; - -procedure _ParserNodeItem(S:string; var ATagName:string; var Attrs:TAttributeDynArray); +procedure _ParserNodeItem(S: string; var ATagName: string; + var Attrs: TAttributeDynArray); var - sc:TSourceContext; + sc: TSourceContext; begin sc.setCode(S); sc.SkipBlank; @@ -501,8 +501,8 @@ procedure _ParserNodeItem(S:string; var ATagName:string; var Attrs:TAttributeDyn _ParserAttrs(sc, Attrs); end; - -function CreateTextElement(AOwner:THtmlElement; AText:string; ALine, ACol:Integer):THtmlElement; +function CreateTextElement(AOwner: THtmlElement; AText: string; + ALine, ACol: Integer): THtmlElement; begin Result := THtmlElement.Create(AOwner, AText, ALine, ACol); with Result do @@ -515,8 +515,8 @@ function CreateTextElement(AOwner:THtmlElement; AText:string; ALine, ACol:Intege end; end; - -function CreateScriptElement(AOwner:THtmlElement; AText:string; ALine, ACol:Integer):THtmlElement; +function CreateScriptElement(AOwner: THtmlElement; AText: string; + ALine, ACol: Integer): THtmlElement; begin Result := THtmlElement.Create(AOwner, AText, ALine, ACol); with Result do @@ -529,8 +529,8 @@ function CreateScriptElement(AOwner:THtmlElement; AText:string; ALine, ACol:Inte end; end; - -function CreateStyleElement(AOwner:THtmlElement; AText:string; ALine, ACol:Integer):THtmlElement; +function CreateStyleElement(AOwner: THtmlElement; AText: string; + ALine, ACol: Integer): THtmlElement; begin Result := THtmlElement.Create(AOwner, AText, ALine, ACol); with Result do @@ -543,8 +543,8 @@ function CreateStyleElement(AOwner:THtmlElement; AText:string; ALine, ACol:Integ end; end; - -function CreateCommentElement(AOwner:THtmlElement; AText:string; ALine, ACol:Integer):THtmlElement; +function CreateCommentElement(AOwner: THtmlElement; AText: string; + ALine, ACol: Integer): THtmlElement; begin Result := THtmlElement.Create(AOwner, AText, ALine, ACol); with Result do @@ -557,11 +557,11 @@ function CreateCommentElement(AOwner:THtmlElement; AText:string; ALine, ACol:Int end; end; - -function CreateTagElement(AOwner:THtmlElement; AText:string; ALine, ACol:Integer):THtmlElement; +function CreateTagElement(AOwner: THtmlElement; AText: string; + ALine, ACol: Integer): THtmlElement; var - I:Integer; - Attrs:TAttributeDynArray; + I: Integer; + Attrs: TAttributeDynArray; begin Result := THtmlElement.Create(AOwner, AText, ALine, ACol); with Result do @@ -588,12 +588,13 @@ function CreateTagElement(AOwner:THtmlElement; AText:string; ALine, ACol:Integer // _ParserNodeItem(AText, FTagName, Attrs); for I := low(Attrs) to high(Attrs) do - FAttributes.AddOrSetValue(LowerCase(Attrs[I].Key), DecodeHtmlEntities(Attrs[I].Value)); + FAttributes.AddOrSetValue(LowerCase(Attrs[I].Key), + DecodeHtmlEntities(Attrs[I].Value)); end; end; - -function CreateDocTypeElement(AOwner:THtmlElement; AText:string; ALine, ACol:Integer):THtmlElement; +function CreateDocTypeElement(AOwner: THtmlElement; AText: string; + ALine, ACol: Integer): THtmlElement; begin Result := THtmlElement.Create(AOwner, AText, ALine, ACol); with Result do @@ -613,22 +614,22 @@ function CreateDocTypeElement(AOwner:THtmlElement; AText:string; ALine, ACol:Int end; end; - -procedure _ParserHTML(const Source:string; AElementList:THtmlElementList); +procedure _ParserHTML(const Source: string; AElementList: THtmlElementList); var - BeginLineNum, BeginColNum:Integer; - sc:TSourceContext; - function IsEndOfTag(TagName:string):Boolean; + BeginLineNum, BeginColNum: Integer; + sc: TSourceContext; + function IsEndOfTag(TagName: string): Boolean; begin Result := false; if sc.charOfCurrent[1] = '/' then begin - Result := UpperCase(sc.subStr(sc.CharIndex + 2, Length(TagName))) = UpperCase(TagName); + Result := UpperCase(sc.subStr(sc.CharIndex + 2, Length(TagName))) + = UpperCase(TagName); end; end; - function PosCharInTag(AChar:Char):Boolean; + function PosCharInTag(AChar: Char): Boolean; var - StrChar:Char; + StrChar: Char; begin Result := false; StrChar := #0; @@ -651,9 +652,9 @@ procedure _ParserHTML(const Source:string; AElementList:THtmlElementList); sc.JumpToNextChar; end; end; - function ParserStyleData():string; + function ParserStyleData(): string; var - oldIndex:Integer; + oldIndex: Integer; begin oldIndex := sc.CharIndex; if sc.subStr(4) = '