Changeset 26 for trunk/UHtmlClasses.pas
- Timestamp:
- Sep 10, 2022, 8:03:08 PM (2 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:ignore
-
old new 7 7 heaptrclog.trc 8 8 MyData.exe 9 MyData.dbg 10
-
- Property svn:ignore
-
trunk/UHtmlClasses.pas
r19 r26 1 1 unit UHtmlClasses; 2 2 3 {$mode delphi}{$H+}4 5 3 interface 6 4 7 5 uses 8 UXmlClasses, Classes, SysUtils, SpecializedList;6 UXmlClasses, Classes, SysUtils, Generics.Collections, UGenerics, UIpAddress; 9 7 10 8 type 11 12 { TDomainAddress } 13 14 TDomainAddress = class(TPersistent) 15 private 16 function GetAsString: string; 17 procedure SetAsString(const Value: string); 18 public 19 Levels: TListString; 20 constructor Create; 21 destructor Destroy; override; 22 property AsString: string read GetAsString write SetAsString; 23 end; 24 25 TAddrClass = (acA, acB, acC, acD, acE); 26 27 { TIpAddress } 28 29 TIpAddress = class(TPersistent) 30 private 31 function GetAddrClass: TAddrClass; 32 function GetAsCardinal: Cardinal; 33 function GetAsString: string; 34 function GetBroadcast: Boolean; 35 procedure SetBroadcast(const Value: Boolean); 36 procedure SetAsCardinal(const Value: Cardinal); 37 procedure SetAsString(const Value: string); 38 public 39 Octets: array[0..3] of Byte; 40 procedure Assign(Source: TPersistent); override; 41 function IsAddressString(Value: string): Boolean; 42 property AsCardinal: Cardinal read GetAsCardinal write SetAsCardinal; 43 property AsString: string read GetAsString write SetAsString; 44 property AddrClass: TAddrClass read GetAddrClass; 45 property Broadcast: Boolean read GetBroadcast write SetBroadcast; 46 end; 47 48 THostAddressState = (asDomainName, asIpAddress); 49 THostAddress = class(TPersistent) 50 private 51 function GetAsString: string; 52 procedure SetAsString(const Value: string); 53 public 54 State: THostAddressState; 55 DomainName: TDomainAddress; 56 IpAddress: TIpAddress; 57 constructor Create; 58 destructor Destroy; override; 59 property AsString: string read GetAsString write SetAsString; 60 end; 9 { TURL } 61 10 62 11 TURL = class(TPersistent) … … 92 41 end; 93 42 43 THtmlString = class; 44 THtmlBlock = class; 45 THtmlList = class; 46 THtmlInput = class; 47 48 { THtmlElements } 49 50 THtmlElements = class(TObjectList<THtmlElement>) 51 function AddString(Text: string = ''): THtmlString; 52 function AddBlock: THtmlBlock; 53 function AddList: THtmlList; 54 function AddInput: THtmlInput; 55 end; 56 94 57 TBlockType = (btNoTag, btBlockLevel, btInline); 95 58 … … 97 60 98 61 THtmlString = class(THtmlElement) 99 pr ivate62 protected 100 63 function GetAsXmlElement: TXmlElement; override; 101 64 public … … 107 70 108 71 THtmlLineBreak = class(THtmlElement) 109 pr ivate72 protected 110 73 function GetAsXmlElement: TXmlElement; override; 111 74 public … … 118 81 public 119 82 BlockType: TBlockType; 120 SubItems: TListObject; // TListObject<THtmlElement>; 83 SubItems: THtmlElements; 84 constructor Create; 85 destructor Destroy; override; 86 end; 87 88 TListType = (ltUnordered, ltOrdered); 89 90 { THtmlList } 91 92 THtmlList = class(THtmlElement) 93 protected 94 function GetAsXmlElement: TXmlElement; override; 95 public 96 ListType: TListType; 97 SubItems: THtmlElements; 121 98 constructor Create; 122 99 destructor Destroy; override; … … 124 101 125 102 THtmlLink = class(THtmlElement) 126 pr ivate103 protected 127 104 function GetAsXmlElement: TXmlElement; override; 128 105 public … … 142 119 143 120 THtmlImage = class(THtmlElement) 144 pr ivate121 protected 145 122 function GetAsXmlElement: TXmlElement; override; 146 123 public … … 158 135 159 136 THtmlInput = class(THtmlElement) 160 pr ivate137 protected 161 138 function GetAsXmlElement: TXmlElement; override; 162 139 public … … 199 176 200 177 THtmlCell = class(THtmlElement) 201 pr ivate178 protected 202 179 function GetAsXmlElement: TXmlElement; override; 203 180 public … … 209 186 end; 210 187 188 { THtmlCells } 189 190 THtmlCells = class(TObjectList<THtmlCell>) 191 function AddCell: THtmlCell; 192 end; 193 211 194 { THtmlRow } 212 195 213 196 THtmlRow = class(THtmlElement) 214 private 215 function GetAsXmlElement: TXmlElement; override; 216 public 217 Cells: TListObject; // TListObject<THtmlCell> 218 constructor Create; 219 destructor Destroy; override; 197 protected 198 function GetAsXmlElement: TXmlElement; override; 199 public 200 Cells: THtmlCells; 201 constructor Create; 202 destructor Destroy; override; 203 end; 204 205 { THtmlRows } 206 207 THtmlRows = class(TObjectList<THtmlRow>) 208 function AddRow: THtmlRow; 220 209 end; 221 210 … … 226 215 function GetAsXmlElement: TXmlElement; override; 227 216 public 228 Rows: T ListObject; // TListObject<THtmlRow>217 Rows: THtmlRows; 229 218 constructor Create; 230 219 destructor Destroy; override; … … 242 231 end; 243 232 233 244 234 implementation 245 246 resourcestring247 SStringToIPConversionError = 'String to IP address conversion error';248 249 235 250 236 function LeftCutString(var Source, Output: string; Delimiter: string; Allowed: string = ''): Boolean; … … 255 241 I := 1; 256 242 Matched := True; 257 while (I < =Length(Source)) and Matched do begin243 while (I < Length(Source)) and Matched do begin 258 244 Matched := False; 259 if (Source[I] >= 'A') and (Source[I] <= 'Z') then Matched := True 260 else if (Source[I] >= 'a') and (Source[I] <= 'z') then Matched := True261 else if (Source[I] >= '0') and (Source[I] <= '9') then Matched := True262 elsefor J := 1 to Length(Allowed) do245 if (Source[I] >= 'A') and (Source[I] <= 'Z') then Matched := True; 246 if (Source[I] >= 'a') and (Source[I] <= 'z') then Matched := True; 247 if (Source[I] >= '0') and (Source[I] <= '9') then Matched := True; 248 for J := 1 to Length(Allowed) do 263 249 if Source[I] = Allowed[J] then Matched := True; 264 250 if Matched then Inc(I); 265 251 end; 266 252 if (Delimiter = Copy(Source, I, Length(Delimiter))) or (I = Length(Source)) then begin 267 Output := Copy(Source, 1, I -1);253 Output := Copy(Source, 1, I-1); 268 254 Delete(Source, 1, Length(Output) + Length(Delimiter)); 269 255 Result := True; … … 300 286 end; 301 287 288 { THtmlCells } 289 290 function THtmlCells.AddCell: THtmlCell; 291 begin 292 Result := THtmlCell.Create; 293 Add(Result); 294 end; 295 296 { THtmlRows } 297 298 function THtmlRows.AddRow: THtmlRow; 299 begin 300 Result := THtmlRow.Create; 301 Add(Result); 302 end; 303 304 { THtmlList } 305 306 function THtmlList.GetAsXmlElement: TXmlElement; 307 var 308 I: Integer; 309 begin 310 Result := TXmlTag.Create; 311 with TXmlTag(Result) do begin 312 case ListType of 313 ltOrdered: Name := 'ol'; 314 ltUnordered: Name := 'ul'; 315 end; 316 for I := 0 to SubItems.Count - 1 do begin 317 with SubElements.AddTag('li') do 318 SubElements.Add(SubItems[I].AsXmlElement); 319 end; 320 end; 321 end; 322 323 constructor THtmlList.Create; 324 begin 325 inherited; 326 SubItems := THtmlElements.Create; 327 end; 328 329 destructor THtmlList.Destroy; 330 begin 331 FreeAndNil(SubItems); 332 inherited; 333 end; 334 335 { THtmlElements } 336 337 function THtmlElements.AddString(Text: string = ''): THtmlString; 338 begin 339 Result := THtmlString.Create; 340 Result.Text := Text; 341 Add(Result); 342 end; 343 344 function THtmlElements.AddBlock: THtmlBlock; 345 begin 346 Result := THtmlBlock.Create; 347 Add(Result); 348 end; 349 350 function THtmlElements.AddList: THtmlList; 351 begin 352 Result := THtmlList.Create; 353 Add(Result); 354 end; 355 356 function THtmlElements.AddInput: THtmlInput; 357 begin 358 Result := THtmlInput.Create; 359 Add(Result); 360 end; 361 302 362 { THtmlCell } 303 363 … … 321 381 destructor THtmlCell.Destroy; 322 382 begin 323 Value.Free;324 inherited Destroy;383 FreeAndNil(Value); 384 inherited; 325 385 end; 326 386 … … 334 394 TXmlTag(Result).Name := 'tr'; 335 395 for Column := 0 to Cells.Count - 1 do 336 TXmlTag(Result).SubElements.Add New(THtmlCell(Cells[Column]).AsXmlElement);396 TXmlTag(Result).SubElements.Add(Cells[Column].AsXmlElement); 337 397 end; 338 398 339 399 constructor THtmlRow.Create; 340 400 begin 341 Cells := T ListObject.Create;401 Cells := THtmlCells.Create; 342 402 end; 343 403 344 404 destructor THtmlRow.Destroy; 345 405 begin 346 Cells.Free;347 inherited Destroy;406 FreeAndNil(Cells); 407 inherited; 348 408 end; 349 409 … … 352 412 function THtmlTable.GetAsXmlElement: TXmlElement; 353 413 var 354 Row , Column: Integer;414 Row: Integer; 355 415 begin 356 416 Result := inherited; … … 358 418 Name := 'table'; 359 419 for Row := 0 to Rows.Count - 1 do 360 SubElements.Add New(THtmlRow(Rows[Row]).AsXmlElement);420 SubElements.Add(Rows[Row].AsXmlElement); 361 421 end; 362 422 end; … … 364 424 constructor THtmlTable.Create; 365 425 begin 366 Rows := T ListObject.Create;426 Rows := THtmlRows.Create; 367 427 end; 368 428 369 429 destructor THtmlTable.Destroy; 370 430 begin 371 Rows.Free;372 inherited Destroy;431 FreeAndNil(Rows); 432 inherited; 373 433 end; 374 434 … … 421 481 constructor THtmlInput.Create; 422 482 begin 423 424 483 end; 425 484 426 485 destructor THtmlInput.Destroy; 427 486 begin 428 inherited Destroy;487 inherited; 429 488 end; 430 489 … … 451 510 destructor THtmlForm.Destroy; 452 511 begin 453 Action.Free;454 inherited Destroy;512 FreeAndNil(Action); 513 inherited; 455 514 end; 456 515 … … 468 527 destructor THtmlDocument.Destroy; 469 528 begin 470 Body.Free;471 Styles.Free;472 Scripts.Free;529 FreeAndNil(Body); 530 FreeAndNil(Styles); 531 FreeAndNil(Scripts); 473 532 inherited; 474 533 end; … … 476 535 function THtmlDocument.GetAsXmlDocument: TXmlDocument; 477 536 var 478 DocType: TXMLTag;479 HTMLTag: TXMLTag;480 537 I: Integer; 481 538 begin 482 539 Result := TXmlDocument.Create; 483 540 with Result, Content do begin 484 DocType := TXMlTag.Create; 485 DocType.Name := '!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"'; 486 Doctype.EndTagSymbol := ''; 487 SubElements.Add(DocType); 488 HTMLTag := TXMLTag.Create; 489 with HTMLTag do begin 490 Name := 'html'; 491 with TXmlTag(SubElements[SubElements.Add(TXmlTag.Create)]) do begin 492 Name := 'head'; 493 with TXmlTag(SubElements[SubElements.Add(TXmlTag.Create)]) do begin 494 Name := 'title'; 495 with TXmlString(SubElements[SubElements.Add(TXmlString.Create)]) do begin 496 Text := Title; 497 end; 541 with SubElements.AddTag('!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"') do begin 542 EndTagSymbol := ''; 543 end; 544 with SubElements.AddTag('html') do begin 545 with SubElements.AddTag('head') do begin 546 with SubElements.AddTag('title') do begin 547 SubElements.AddString(Title); 498 548 end; 499 with TXmlTag(SubElements[SubElements.Add(TXmlTag.Create)]) do begin 500 Name := 'meta'; 549 with SubElements.AddTag('meta') do begin 501 550 Attributes.Add('http-equiv', 'Content-Language'); 502 551 Attributes.Add('content', ContentLanguage); 503 552 end; 504 with TXmlTag(SubElements[SubElements.Add(TXmlTag.Create)]) do begin 505 Name := 'meta'; 553 with SubElements.AddTag('meta') do begin 506 554 Attributes.Add('http-equiv', 'Content-Type'); 507 555 Attributes.Add('content', 'text/html; charset=' + ContentEncoding); 508 556 end; 557 with SubElements.AddTag('meta') do begin 558 Attributes.Add('name', 'viewport'); 559 Attributes.Add('content', 'width=device-width, initial-scale=1'); 560 end; 509 561 for I := 0 to Styles.Count - 1 do 510 with TXmlTag(SubElements[SubElements.Add(TXmlTag.Create)]) do begin 511 Name := 'link'; 562 with SubElements.AddTag('link') do begin 512 563 Attributes.Add('rel', 'stylesheet'); 513 564 Attributes.Add('href', Styles[I]); … … 516 567 end; 517 568 for I := 0 to Scripts.Count - 1 do 518 with TXmlTag(SubElements[SubElements.Add(TXmlTag.Create)]) do begin 519 Name := 'script'; 569 with SubElements.AddTag('script') do begin 520 570 ShringEmpty := False; 521 571 Attributes.Add('type', 'text/javascript'); … … 523 573 end; 524 574 end; 525 with TXmlTag(SubElements[SubElements.Add(TXmlTag.Create)]) do begin 526 Name := 'body'; 575 with SubElements.AddTag('body') do begin 527 576 SubElements.Add(Body.AsXmlElement); 528 577 end; 529 578 end; 530 SubElements.Add(HTMLTag);531 579 end; 532 580 end; … … 537 585 begin 538 586 inherited; 539 SubItems := T ListObject.Create;587 SubItems := THtmlElements.Create; 540 588 end; 541 589 542 590 destructor THtmlBlock.Destroy; 543 591 begin 544 SubItems.Free;592 FreeAndNil(SubItems); 545 593 inherited; 546 594 end; … … 558 606 end; 559 607 for I := 0 to SubItems.Count - 1 do 560 SubElements.Add( THtmlElement(SubItems[I]).AsXmlElement);608 SubElements.Add(SubItems[I].AsXmlElement); 561 609 end; 562 610 end; … … 583 631 end; 584 632 585 { TIpAddress } 586 587 procedure TIpAddress.Assign(Source: TPersistent); 588 var 589 I: Integer; 590 begin 591 if Assigned(Source) then begin 592 if Source is TIpAddress then begin 593 for I := 0 to High(Octets) do 594 Octets[I] := TIpAddress(Source).Octets[I]; 595 end else inherited; 596 end else inherited; 597 end; 598 599 function TIpAddress.IsAddressString(Value: string): Boolean; 600 var 601 Parts: TListString; 602 begin 603 Result := True; 604 try 605 Parts := TListString.Create; 606 Parts.Explode(Value, '.', StrToStr); 607 if Parts.Count = 4 then begin 608 if (StrToInt(Parts[3]) < 0) or (StrToInt(Parts[3]) > 255) then Result := False; 609 if (StrToInt(Parts[2]) < 0) or (StrToInt(Parts[2]) > 255) then Result := False; 610 if (StrToInt(Parts[1]) < 0) or (StrToInt(Parts[1]) > 255) then Result := False; 611 if (StrToInt(Parts[0]) < 0) or (StrToInt(Parts[0]) > 255) then Result := False; 612 end else Result := False; 613 finally 614 Parts.Free; 615 end; 616 end; 617 618 function TIpAddress.GetAddrClass: TAddrClass; 619 begin 620 if (Octets[3] and $80) = 0 then Result := acA 621 else begin 622 if (Octets[3] and $40) = 0 then Result := acB 623 else begin 624 if (Octets[3] and $20) = 0 then Result := acC 625 else begin 626 if (Octets[3] and $10) = 0 then Result := acD 627 else Result := acE; 628 end; 629 end; 630 end; 631 end; 632 633 function TIpAddress.GetAsCardinal: Cardinal; 634 begin 635 Result := Octets[0] or (Octets[1] shl 8) or (Octets[2] shl 16) or (Octets[3] shl 24); 636 end; 637 638 function TIpAddress.GetAsString: string; 639 begin 640 Result := IntToStr(Octets[3]) + '.' + IntToStr(Octets[2]) + '.' + 641 IntToStr(Octets[1]) + '.' + IntToStr(Octets[0]); 642 end; 643 644 function TIpAddress.GetBroadcast: Boolean; 645 begin 646 Result := AsCardinal = High(Cardinal); 647 end; 648 649 procedure TIpAddress.SetAsCardinal(const Value: Cardinal); 650 begin 651 Octets[0] := Byte(Value); 652 Octets[1] := Byte(Value shr 8); 653 Octets[2] := Byte(Value shr 16); 654 Octets[3] := Byte(Value shr 24); 655 end; 656 657 procedure TIpAddress.SetAsString(const Value: string); 658 var 659 Parts: TListString; 660 begin 661 try 662 Parts := TListString.Create; 663 Parts.Explode(Value, '.', StrToStr); 664 try 665 // if Length(Parts) = 4 then begin 666 Octets[0] := StrToInt(Parts[3]); 667 Octets[1] := StrToInt(Parts[2]); 668 Octets[2] := StrToInt(Parts[1]); 669 Octets[3] := StrToInt(Parts[0]); 670 // end else raise EConvertError.Create('String to IP address conversion error'); 671 except 672 raise EConvertError.Create(SStringToIPConversionError); 673 end; 674 finally 675 Parts.Free; 676 end; 677 end; 678 679 procedure TIpAddress.SetBroadcast(const Value: Boolean); 680 begin 681 AsCardinal := High(Cardinal); 682 end; 633 { TURL } 683 634 684 635 constructor TURL.Create; … … 689 640 destructor TURL.Destroy; 690 641 begin 691 Host.Free;642 FreeAndNil(Host); 692 643 inherited; 693 644 end; … … 724 675 end else LeftCutString(Value, HostAddr, '', '.'); 725 676 Host.AsString := HostAddr; 726 LeftCutString(Value, Path, '', '/._'); 727 end; 728 729 730 { TDomainAddress } 731 732 function TDomainAddress.GetAsString: string; 733 begin 734 try 735 Levels.Reverse; 736 Result := Levels.Implode('.', StrToStr); 737 finally 738 Levels.Reverse; 739 end; 740 end; 741 742 procedure TDomainAddress.SetAsString(const Value: string); 743 begin 744 Levels.Explode(Value, '.', StrToStr); 745 Levels.Reverse; 746 end; 747 748 constructor TDomainAddress.Create; 749 begin 750 Levels := TListString.Create; 751 end; 752 753 destructor TDomainAddress.Destroy; 754 begin 755 Levels.Free; 756 inherited Destroy; 677 LeftCutString(Value, Path, '', '/.'); 757 678 end; 758 679 … … 766 687 destructor THtmlLink.Destroy; 767 688 begin 768 Target.Free;689 FreeAndNil(Target); 769 690 inherited; 770 691 end; … … 794 715 end; 795 716 796 { THostAddress }797 798 constructor THostAddress.Create;799 begin800 DomainName := TDomainAddress.Create;801 IpAddress := TIpAddress.Create;802 State := asDomainName;803 DomainName.AsString := 'localhost';804 end;805 806 destructor THostAddress.Destroy;807 begin808 DomainName.Free;809 IpAddress.Free;810 inherited;811 end;812 813 function THostAddress.GetAsString: string;814 begin815 case State of816 asDomainName: Result := DomainName.AsString;817 asIpAddress: Result := IpAddress.AsString;818 end;819 end;820 821 procedure THostAddress.SetAsString(const Value: string);822 begin823 if IpAddress.IsAddressString(Value) then begin824 State := asIpAddress;825 IpAddress.AsString := Value;826 end else begin827 State := asDomainName;828 DomainName.AsString := Value;829 end;830 end;831 832 717 { THtmlImage } 833 718 … … 839 724 destructor THtmlImage.Destroy; 840 725 begin 841 Source.Free;726 FreeAndNil(Source); 842 727 inherited; 843 728 end; … … 892 777 destructor TQueryString.Destroy; 893 778 begin 894 Data.Free;895 inherited Destroy;779 FreeAndNil(Data); 780 inherited; 896 781 end; 897 782
Note:
See TracChangeset
for help on using the changeset viewer.