mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-12 05:21:27 +02:00
Turbopower_ipro: Refactor unit ipHtml by extracting parser into separate unit.
This commit is contained in:
parent
4e92b0a028
commit
4a9da60a1d
836
components/turbopower_ipro/ipcss.pas
Normal file
836
components/turbopower_ipro/ipcss.pas
Normal file
@ -0,0 +1,836 @@
|
||||
unit IpCSS;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, Contnrs, SysUtils, Graphics,
|
||||
IpHtmlProp, IpHtmlUtils;
|
||||
|
||||
type
|
||||
TCSSGroup = class
|
||||
end;
|
||||
|
||||
TCSSFontStyle = (cfsNormal, cfsItalic, cfsOblique, cfsInherit);
|
||||
TCSSFontWeight = (cfwNormal, cfwBold, cfwBolder, cfwLighter, cfw100, cfw200,
|
||||
cfw300, cfw400 , cfw500, cfw600, cfw700, cfw800, cfw900);
|
||||
TCSSFontVariant = (cfvNormal, cfvSmallCaps, cfvInherit);
|
||||
|
||||
TCSSBorderStyle = (cbsNone, cbsHidden, cbsDotted, cbsDashed, cbsSolid, cbsDouble,
|
||||
cbsGroove, cbsRidge, cbsInset, cbsOutset);
|
||||
TCSSMarginStyle = (cmsNone,
|
||||
cmsAuto, // use default
|
||||
cmsPx, // pixel
|
||||
cmsPt, cmsEm, cmsPercent // currently not supported
|
||||
);
|
||||
|
||||
TCSSMargin = record
|
||||
Style: TCSSMarginStyle;
|
||||
Size: single; // negative values are allowed (not implemented)
|
||||
end;
|
||||
|
||||
TCSSLengthType = (cltUndefined, cltAbsolute, cltPercent);
|
||||
TCSSLength = record
|
||||
LengthValue: Integer;
|
||||
LengthType: TCSSLengthType
|
||||
end;
|
||||
|
||||
{ TCSSFont }
|
||||
|
||||
TCSSFont = class
|
||||
private
|
||||
FFamily: String;
|
||||
FSize: String;
|
||||
FStyle: TCSSFontStyle;
|
||||
FWeight: TCSSFontWeight;
|
||||
published
|
||||
property Name: String read FFamily write FFamily;
|
||||
property Size: String read FSize write FSize;
|
||||
property Style: TCSSFontStyle read FStyle write FStyle;
|
||||
//proprety Variant: TCSSFontVariant
|
||||
property Weight: TCSSFontWeight read FWeight write FWeight;
|
||||
end;
|
||||
|
||||
{ TCSSBorder }
|
||||
|
||||
TCSSBorder = class
|
||||
private
|
||||
FColor: TColor;
|
||||
FStyle: TCSSBorderStyle;
|
||||
FWidth: Integer;
|
||||
public
|
||||
constructor Create;
|
||||
published
|
||||
property Color: TColor read FColor write FColor;
|
||||
property Style: TCSSBorderStyle read FStyle write FStyle;
|
||||
property Width: Integer read FWidth write FWidth;
|
||||
end;
|
||||
|
||||
{ TCSSProps represents a set of properties from the CSS stylesheet, for
|
||||
example everything within one selector or the contents of a style attribute
|
||||
or even many applicable CSS styles for one node merged into one. It has
|
||||
methods for parsing CSS text and for merging two such objects into one}
|
||||
TCSSProps = class
|
||||
private
|
||||
FBorder: TCSSBorder;
|
||||
FClassIDs: TStringList;
|
||||
FBGColor: TColor;
|
||||
FBorderBottom: TCSSBorderStyle;
|
||||
FBorderLeft: TCSSBorderStyle;
|
||||
FBorderRight: TCSSBorderStyle;
|
||||
FBorderTop: TCSSBorderStyle;
|
||||
FColor: TColor;
|
||||
FFont: TCSSFont;
|
||||
FAlignment: TIpHtmlAlign;
|
||||
FMarginBottom: TCSSMargin;
|
||||
FMarginLeft: TCSSMargin;
|
||||
FMarginRight: TCSSMargin;
|
||||
FMarginTop: TCSSMargin;
|
||||
FWidth: TCSSLength;
|
||||
function GetCommandArgs(ACommand: String): TStringList;
|
||||
function GetCommandName(ACommand: String): String;
|
||||
public
|
||||
property MarginTop: TCSSMargin read FMarginTop write FMarginTop;
|
||||
property MarginLeft: TCSSMargin read FMarginLeft write FMarginLeft;
|
||||
property MarginBottom: TCSSMargin read FMarginBottom write FMarginBottom;
|
||||
property MarginRight: TCSSMargin read FMarginRight write FMarginRight;
|
||||
property Width: TCSSLength read FWidth write FWidth;
|
||||
published
|
||||
property Font: TCSSFont read FFont write FFont;
|
||||
property Color: TColor read FColor write FColor;
|
||||
property BGColor: TColor read FBGColor write FBGColor;
|
||||
property Border: TCSSBorder read FBorder write FBorder;
|
||||
property BorderTop: TCSSBorderStyle read FBorderTop write FBorderTop;
|
||||
property BorderLeft: TCSSBorderStyle read FBorderLeft write FBorderLeft;
|
||||
property BorderBottom: TCSSBorderStyle read FBorderBottom write FBorderBottom;
|
||||
property BorderRight: TCSSBorderStyle read FBorderRight write FBorderRight;
|
||||
property Alignment: TIpHtmlAlign read FAlignment write FAlignment;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure ReadCommands(ACommands: TStrings);
|
||||
procedure MergeAdditionalProps(AProps: TCSSProps);
|
||||
end;
|
||||
|
||||
{ TCSSGlobalProps serves as a global list of TCSSProps objects, it is
|
||||
populated when parsing the CSS and then used to look up the CSS styles
|
||||
for a certain CSS selector (the selector is supplied as a string and it
|
||||
returns a reference to the TCSSProps object for this selector). The
|
||||
contained TCSSProps objects are created and owned by TCSSGlobalProps }
|
||||
TCSSGlobalProps = class
|
||||
FElements: TFPObjectHashTable;
|
||||
protected
|
||||
{$IFDEF IP_LAZARUS_DBG}
|
||||
procedure DoDumpProps(Item: TObject; const Key: String; var Continue: Boolean);
|
||||
{$ENDIF}
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
{$IFDEF IP_LAZARUS_DBG}
|
||||
procedure DumpProps;
|
||||
{$ENDIF}
|
||||
function GetPropsObject(ATagName: String; AClassID: String = ''; CreateIfNotExist: Boolean = False): TCSSProps;
|
||||
end;
|
||||
|
||||
TCSSReader = class
|
||||
FStream: TStream;
|
||||
FGlobalProps: TCSSGlobalProps;
|
||||
function GetStatementElements(AStatement: String): TStringList;
|
||||
function GetStatementCommands(AStatement: String): TStringList;
|
||||
function CheckIsComment: Boolean;
|
||||
procedure EatWhiteSpace;
|
||||
procedure ParseCSS;
|
||||
procedure EatComment;
|
||||
function FindStatement(out AStatement: String): Boolean;
|
||||
function EOF: Boolean;
|
||||
constructor Create(AStream: TStream; AGlobalProps: TCSSGlobalProps);
|
||||
end;
|
||||
|
||||
function SeparateCommands(Commands: String): TStringList;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
LazStringUtils;
|
||||
|
||||
function ForceRange(x, xmin, xmax: Integer): Integer;
|
||||
begin
|
||||
if x < xmin then
|
||||
Result := xmin
|
||||
else if x > xmax then
|
||||
Result := xmax
|
||||
else
|
||||
Result := x;
|
||||
end;
|
||||
|
||||
function IsWhiteSpace(AChar: Char; ExcludeSpaces: Boolean = False): Boolean;
|
||||
begin
|
||||
Result := AChar in [#9, #10, #11, #13];
|
||||
if not Result and not ExcludeSpaces then
|
||||
Result := AChar = ' ';
|
||||
end;
|
||||
|
||||
function StrToCSSLength(AValue: String): TCssLength;
|
||||
var
|
||||
P, Err: Integer;
|
||||
begin
|
||||
P := Pos('%', AValue);
|
||||
if P <> 0 then begin
|
||||
Result.LengthType := cltPercent;
|
||||
Delete(AValue, P, 1);
|
||||
end else
|
||||
Result.LengthType := cltAbsolute;
|
||||
val(AValue, Result.LengthValue, Err);
|
||||
if (Err <> 0) or (Result.LengthValue < 0) then
|
||||
Result.LengthType := cltUndefined
|
||||
else if (Result.LengthType = cltPercent) and (Result.LengthValue > 100) then
|
||||
Result.LengthValue := 100;
|
||||
end;
|
||||
|
||||
function SeparateCommands(Commands: String): TStringList;
|
||||
var
|
||||
i, fpos1, fpos2: Integer;
|
||||
Command: String;
|
||||
begin
|
||||
Result := TStringList.Create;
|
||||
FPos1 := 1;
|
||||
|
||||
for i := 1 to Length(Commands) do
|
||||
begin
|
||||
if Commands[i] = ';' then
|
||||
begin
|
||||
Command := Copy(Commands, FPos1, i-FPos1);
|
||||
FPos1 := i+1;
|
||||
for FPos2 := Length(Command) downto 1 do
|
||||
if IsWhiteSpace(Command[FPos2], True) then
|
||||
Delete(Command, FPos2, 1);
|
||||
Result.Add(Trim(Command));
|
||||
end;
|
||||
end;
|
||||
Command := Trim(Copy(Commands, FPos1, Length(Commands)));
|
||||
if Command <> '' then
|
||||
begin
|
||||
Result.Add(Command);
|
||||
end;
|
||||
end;
|
||||
|
||||
function FontWeightFromString(S: String): TCSSFontWeight;
|
||||
begin
|
||||
Result := cfwNormal;
|
||||
S := trim(S);
|
||||
case S[1] of
|
||||
'1': if S = '100' then Result := cfw100;
|
||||
'2': if S = '200' then Result := cfw200;
|
||||
'3': if S = '300' then Result := cfw300;
|
||||
'4': if S = '400' then Result := cfw400;
|
||||
'5': if S = '500' then Result := cfw500;
|
||||
'6': if S = '600' then Result := cfw600;
|
||||
'7': if S = '700' then Result := cfw700;
|
||||
'8': if S = '800' then Result := cfw800;
|
||||
'9': if S = '900' then Result := cfw900;
|
||||
'B','b': if CompareText(S, 'bold') = 0 then Result := cfwBold
|
||||
else if CompareText(S, 'bolder') = 0 then Result := cfwBolder;
|
||||
'L','l': if CompareText(S, 'lighter') = 0 then Result := cfwLighter;
|
||||
end;
|
||||
end;
|
||||
|
||||
function SizePxFromString(S: String): Integer;
|
||||
begin
|
||||
S := Copy(S, 1, PosI('px', S)-1);
|
||||
Result := StrToIntDef(S, 0);
|
||||
end;
|
||||
|
||||
function StrToCssMargin(const S: string): TCSSMargin;
|
||||
var
|
||||
i: SizeInt;
|
||||
begin
|
||||
Result.Style:=cmsAuto;
|
||||
Result.Size:=0;
|
||||
if (S='') or (CompareText(S,'auto')=0) then exit;
|
||||
|
||||
i:=PosI('px',S);
|
||||
if i>0 then begin
|
||||
Result.Style:=cmsPx;
|
||||
Result.Size:=StrToIntDef(copy(S,1,i-1),0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
i:=PosI('em',S);
|
||||
if i>0 then begin
|
||||
Result.Style:=cmsEm;
|
||||
Result.Size:=StrToIntDef(copy(S,1,i-1),0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
i:=Pos('%',S);
|
||||
if i>0 then begin
|
||||
Result.Style:=cmsPercent;
|
||||
Result.Size:=StrToIntDef(copy(S,1,i-1),0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// a number without unit is px
|
||||
Result.Style:=cmsPx;
|
||||
Result.Size:=StrToIntDef(S,0);
|
||||
end;
|
||||
|
||||
function CSSFontStyleFromName(S: String): TCSSFontStyle;
|
||||
begin
|
||||
Result := cfsNormal;
|
||||
if length(s)<2 then exit;
|
||||
case S[2] of
|
||||
'b': if S = 'oblique' then Result := cfsOblique;
|
||||
'n': if S = 'inherit' then Result := cfsInherit;
|
||||
't': if S = 'italic' then Result := cfsItalic;
|
||||
end;
|
||||
end;
|
||||
|
||||
function BorderStyleFromString(S: String): TCSSBorderStyle;
|
||||
begin
|
||||
Result := cbsNone;
|
||||
S := LowerCase(S);
|
||||
case S[1] of
|
||||
'd':
|
||||
if S = 'dotted' then
|
||||
Result := cbsDotted
|
||||
else
|
||||
if S = 'dashed' then
|
||||
Result := cbsDashed
|
||||
else
|
||||
if S = 'double' then
|
||||
Result := cbsDouble;
|
||||
'g': if S = 'groove' then Result := cbsGroove;
|
||||
'h': if S = 'hidden' then Result := cbsHidden;
|
||||
'i': if S = 'inset' then Result := cbsInset;
|
||||
'o': if S = 'outset' then Result := cbsOutset;
|
||||
'r': if S = 'ridge' then Result := cbsRidge;
|
||||
's': if S = 'solid' then Result := cbsSolid;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ TCSSReader }
|
||||
|
||||
function TCSSReader.GetStatementElements(AStatement: String): TStringList;
|
||||
var
|
||||
i, fpos: Integer;
|
||||
Elements : String;
|
||||
Element: String;
|
||||
ElementClass: String;
|
||||
begin
|
||||
Result := TStringList.Create;
|
||||
fpos := Pos('{', AStatement);
|
||||
if fpos > 0 then
|
||||
begin
|
||||
Elements := Copy(AStatement,1,fpos-1);
|
||||
for i := Length(Elements) downto 1 do
|
||||
if IsWhiteSpace(Elements[i]) then
|
||||
Delete(Elements, i, 1);
|
||||
Result.Delimiter := ',';
|
||||
Result.DelimitedText := Elements;
|
||||
end;
|
||||
|
||||
for i := 0 to Result.Count-1 do begin
|
||||
{$IFDEF CSS_CASESENSITIVE_CLASSID}
|
||||
Element := Result[i];
|
||||
{$ELSE}
|
||||
Element := LowerCase(Result[i]);
|
||||
{$ENDIF}
|
||||
ElementClass := '';
|
||||
fpos := Pos('.', Element);
|
||||
if fpos = 0 then
|
||||
begin
|
||||
Result.Objects[i] := FGlobalProps.GetPropsObject(Element, '', True);
|
||||
end
|
||||
else begin
|
||||
{$IFDEF CSS_CASESENSITIVE_CLASSID}
|
||||
ElementClass := Copy(Element, FPos+1, Length(Element));
|
||||
Element := Copy(Element, 1, FPos-1);
|
||||
{$ELSE}
|
||||
ElementClass := LowerCase(Copy(Element, FPos+1, Length(Element)));
|
||||
Element := LowerCase(Copy(Element, 1, FPos-1));
|
||||
{$ENDIF}
|
||||
Result.Objects[i] := FGlobalProps.GetPropsObject(Element, ElementClass, True);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
function TCSSReader.GetStatementCommands(AStatement: String): TStringList;
|
||||
var
|
||||
fpos1, fpos2: Integer;
|
||||
Commands: String;
|
||||
begin
|
||||
fpos1 := Pos('{', AStatement)+1;
|
||||
fpos2 := Pos('}', AStatement)-1;
|
||||
Commands := Copy(AStatement, fpos1, fpos2-fpos1+1);
|
||||
Result := SeparateCommands(Commands);
|
||||
end;
|
||||
|
||||
function TCSSProps.GetCommandArgs(ACommand: String): TStringList;
|
||||
var
|
||||
i: Integer;
|
||||
WantArg: Boolean;
|
||||
Arg: String;
|
||||
Start: Integer;
|
||||
Quote: char;
|
||||
WantChar: Boolean;
|
||||
WantPar: Boolean;
|
||||
Len: Integer;
|
||||
begin
|
||||
Result := TStringList.Create;
|
||||
Start := Pos(':', ACommand)+1;
|
||||
|
||||
WantArg := True;
|
||||
WantPar := false;
|
||||
Quote := #0;
|
||||
for i := Start to Length(ACommand) do
|
||||
begin
|
||||
if (Quote = #0) and (ACommand[i] in ['"','''']) then
|
||||
begin
|
||||
Quote := ACommand[i];
|
||||
Start := i+1;
|
||||
continue;
|
||||
end;
|
||||
if Quote<>#0 then begin
|
||||
if ACommand[i]=Quote then begin
|
||||
Quote:=#0;
|
||||
Arg := Copy(ACommand, Start, i-Start);
|
||||
Result.Add(Arg);
|
||||
end;
|
||||
continue;
|
||||
end;
|
||||
if WantArg then
|
||||
begin
|
||||
if IsWhiteSpace(ACommand[i]) then
|
||||
Continue;
|
||||
Start := i;
|
||||
WantArg := False;
|
||||
continue;
|
||||
end
|
||||
else // we have an arg we are reading ...
|
||||
begin
|
||||
WantChar:=not (ACommand[i] in [';',' ',#9]);
|
||||
if ACommand[i] = '(' then WantPar := True;
|
||||
if ACommand[i] = ')' then WantPar := False;
|
||||
if (i<Length(ACommand)) and (WantChar or WantPar)
|
||||
then
|
||||
continue;
|
||||
WantArg := True;
|
||||
Len:=i-Start;
|
||||
if WantChar then inc(Len);
|
||||
Arg := Copy(ACommand, Start, Len);
|
||||
Result.Add(Arg);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCSSProps.GetCommandName(ACommand: String): String;
|
||||
begin
|
||||
Result := Copy(ACommand, 1, Pos(':', ACommand)-1);
|
||||
end;
|
||||
|
||||
function TCSSReader.CheckIsComment: Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if EOF then
|
||||
exit;
|
||||
Result := char(FStream.ReadByte) = '*';
|
||||
if not Result then
|
||||
FStream.Position := FStream.Position-1;
|
||||
end;
|
||||
|
||||
procedure TCSSReader.EatWhiteSpace;
|
||||
var
|
||||
Buf: char;
|
||||
//comment: integer;
|
||||
begin
|
||||
//comment:=0;
|
||||
while not EOF do
|
||||
begin
|
||||
Buf := char(FStream.ReadByte);
|
||||
if (Buf = '/') and not EOF then
|
||||
begin
|
||||
if CheckIsComment then
|
||||
begin
|
||||
EatComment;
|
||||
Buf := ' ';
|
||||
end;
|
||||
end;
|
||||
if (IsWhiteSpace(Buf) = False) then
|
||||
begin
|
||||
FStream.Position := FStream.Position-1;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCSSReader.ParseCSS;
|
||||
var
|
||||
Statement: String;
|
||||
Elements: TStringList;
|
||||
Commands: TStringList;
|
||||
Element: TCSSProps;
|
||||
I: Integer;
|
||||
begin
|
||||
while FindStatement(Statement) do begin
|
||||
Elements := GetStatementElements(Statement);
|
||||
Commands := GetStatementCommands(Statement);
|
||||
try
|
||||
for I := 0 to Elements.Count-1 do
|
||||
begin
|
||||
Element := TCSSProps(Elements.Objects[I]);
|
||||
Element.ReadCommands(Commands);
|
||||
end;
|
||||
finally
|
||||
Elements.Free;
|
||||
Commands.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCSSReader.EatComment;
|
||||
var
|
||||
Buf: array[0..1] of char;
|
||||
begin
|
||||
Buf := #0#0;
|
||||
while (EOF = False) and (Buf <> '*/') do
|
||||
begin
|
||||
Buf[0] := Buf[1];
|
||||
FStream.Read(Buf[1], 1);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCSSReader.FindStatement(out AStatement: String): Boolean;
|
||||
var
|
||||
Buf: char;
|
||||
Buf1: string;
|
||||
RCount: Integer;
|
||||
FStart, FEnd: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
EatWhiteSpace;
|
||||
|
||||
AStatement := '';
|
||||
|
||||
SetLength(Buf1,1023);
|
||||
FStart := FStream.Position;
|
||||
while not EOF do
|
||||
begin
|
||||
|
||||
Buf := Char(FStream.ReadByte);
|
||||
FEnd := FStream.Position;
|
||||
if (Buf = '/') and CheckIsComment then
|
||||
begin
|
||||
FStream.Position := FStart;
|
||||
if length(Buf1)<FEnd-FStart then
|
||||
setlength(Buf1,FEnd-FStart);
|
||||
RCount := FStream.Read(Buf1[1], FEnd-FStart-1);
|
||||
AStatement := AStatement + Copy(Buf1,0,RCount);
|
||||
FStream.Position := FEnd+1;
|
||||
EatComment;
|
||||
FStart := FStream.Position;
|
||||
end
|
||||
else if Buf = '}' then
|
||||
begin
|
||||
Result := True;
|
||||
FStream.Position := FStart;
|
||||
if length(Buf1)<FEnd-FStart then
|
||||
setlength(Buf1,FEnd-FStart);
|
||||
RCount := FStream.Read(Buf1[1], FEnd-FStart);
|
||||
AStatement := AStatement + Copy(Buf1,0,RCount);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCSSReader.EOF: Boolean;
|
||||
begin
|
||||
Result := FStream.Position >= FStream.Size;
|
||||
end;
|
||||
|
||||
constructor TCSSReader.Create(AStream: TStream; AGlobalProps: TCSSGlobalProps);
|
||||
begin
|
||||
inherited Create;
|
||||
FStream := AStream;
|
||||
FGlobalProps:= AGlobalProps;
|
||||
end;
|
||||
|
||||
{ TCSSProps }
|
||||
|
||||
constructor TCSSProps.Create;
|
||||
begin
|
||||
FFont := TCSSFont.Create;
|
||||
FBGColor := clNone;
|
||||
FColor := clNone;
|
||||
FAlignment := haUnknown;
|
||||
FBorder := TCSSBorder.Create;
|
||||
FWidth.LengthType := cltUndefined;
|
||||
end;
|
||||
|
||||
destructor TCSSProps.Destroy;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if Assigned(FClassIDs) then
|
||||
begin
|
||||
for i := 0 to FClassIDs.Count-1 do
|
||||
FClassIDs.Objects[i].Free;
|
||||
FClassIDs.Free;
|
||||
end;
|
||||
FFont.Free;
|
||||
FBorder.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TCSSProps.ReadCommands(ACommands: TStrings);
|
||||
var
|
||||
Args: TStringlist;
|
||||
ACommand: String;
|
||||
Cmd: String;
|
||||
I: Integer;
|
||||
begin
|
||||
for I := 0 to ACommands.Count-1 do
|
||||
begin
|
||||
ACommand := ACommands[I];
|
||||
if ACommand='' then continue;
|
||||
Cmd := LowerCase(GetCommandName(ACommand));
|
||||
if Cmd='' then continue;
|
||||
|
||||
Args := GetCommandArgs(ACommand);
|
||||
try
|
||||
case Cmd[1] of
|
||||
'c': if Cmd = 'color' then
|
||||
if Args.Count > 0 then
|
||||
Color := ColorFromString(Args[0])
|
||||
else
|
||||
Color := clDefault;
|
||||
|
||||
'b': if Cmd = 'background-color' then begin
|
||||
if Args.Count > 0 then
|
||||
BGColor := ColorFromString(Args[0])
|
||||
else
|
||||
BGColor := clDefault;
|
||||
end else
|
||||
if Cmd = 'background' then
|
||||
begin
|
||||
if Args.Count > 0 then BGColor := ColorFromString(Args[0]);
|
||||
if Args.Count > 1 then ; // background image
|
||||
if Args.Count > 2 then ; // background image repeat
|
||||
if Args.Count > 3 then ; // background attachment
|
||||
if Args.Count > 4 then ; // background position
|
||||
end
|
||||
else if Cmd = 'border' then
|
||||
begin
|
||||
if Args.Count > 0 then Border.Width := SizePxFromString(Args[0]);
|
||||
if Args.Count > 1 then Border.Style := BorderStyleFromString(Args[1]);
|
||||
if Args.Count > 2 then Border.Color := ColorFromString(Args[2]);
|
||||
end
|
||||
else if Cmd = 'border-width' then
|
||||
begin
|
||||
if Args.Count > 0 then Border.Width := SizePxFromString(Args[0]);
|
||||
end
|
||||
else if Cmd = 'border-color' then
|
||||
begin
|
||||
if Args.Count > 0 then Border.Color := ColorFromString(Args[0]);
|
||||
end
|
||||
else if Cmd = 'border-style' then
|
||||
begin
|
||||
if Args.Count > 0 then Border.Style := BorderStyleFromString(Args[0]);
|
||||
end;
|
||||
|
||||
'm':
|
||||
if Cmd = 'margin-top' then begin
|
||||
if Args.Count > 0 then MarginTop := StrToCssMargin(Args[0]);
|
||||
end
|
||||
else if Cmd = 'margin-left' then begin
|
||||
if Args.Count > 0 then MarginLeft := StrToCssMargin(Args[0]);
|
||||
end
|
||||
else if Cmd = 'margin-bottom' then begin
|
||||
if Args.Count > 0 then MarginBottom := StrToCssMargin(Args[0]);
|
||||
end else if Cmd = 'margin-right' then begin
|
||||
if Args.Count > 0 then MarginRight := StrToCssMargin(Args[0]);
|
||||
end else if Cmd = 'margin' then begin
|
||||
case Args.Count of
|
||||
1:begin
|
||||
// 1 arg: all four the same
|
||||
MarginTop := StrToCssMargin(Args[0]);
|
||||
MarginBottom := MarginTop;
|
||||
MarginLeft := MarginTop;
|
||||
MarginRight := MarginTop;
|
||||
end;
|
||||
2:begin
|
||||
// 2 args: top+bottom and left+right
|
||||
MarginTop := StrToCssMargin(Args[0]);
|
||||
MarginBottom := MarginTop;
|
||||
MarginLeft := StrToCssMargin(Args[1]);
|
||||
MarginRight := MarginLeft;
|
||||
end;
|
||||
3:begin
|
||||
// 3 args: top right bottom
|
||||
MarginTop := StrToCssMargin(Args[0]);
|
||||
MarginRight := StrToCssMargin(Args[1]);
|
||||
MarginBottom := StrToCssMargin(Args[2]);
|
||||
end;
|
||||
4:begin
|
||||
// 4 args: top right bottom left
|
||||
MarginTop := StrToCssMargin(Args[0]);
|
||||
MarginRight := StrToCssMargin(Args[1]);
|
||||
MarginBottom := StrToCssMargin(Args[2]);
|
||||
MarginLeft := StrToCssMargin(Args[3]);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
't': if (Cmd = 'text-align') then
|
||||
begin
|
||||
if Args.Count > 0 then Alignment := GetAlignmentForStr(Args[0]);
|
||||
end;
|
||||
|
||||
'f':
|
||||
if (Length(Cmd) > 7) and (Args.Count > 0) then
|
||||
case Cmd[7] of
|
||||
'a': if (Cmd = 'font-family') then
|
||||
Font.Name := Args.CommaText; //Args[0];
|
||||
'i': if (Cmd = 'font-size') then
|
||||
Font.Size := Args[0];
|
||||
't': if (Cmd = 'font-style') then
|
||||
Font.Style := CSSFontStyleFromName(Args[0]);
|
||||
'e': if (Cmd = 'font-weight') then
|
||||
Font.Weight := FontWeightFromString(Args[0]);
|
||||
end;
|
||||
'w':
|
||||
if (Cmd = 'width') and (Args.Count > 0) then
|
||||
FWidth := StrToCSSLength(Args[0]);
|
||||
end;
|
||||
finally
|
||||
Args.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCSSProps.MergeAdditionalProps(AProps: TCSSProps);
|
||||
begin
|
||||
if AProps.Color <> clNone then Color := AProps.Color;
|
||||
if AProps.BGColor <> clNone then BGColor := AProps.BGColor;
|
||||
if AProps.Alignment <> haUnknown then Alignment := AProps.Alignment;
|
||||
if AProps.Font.Name <> '' then Font.Name := AProps.Font.Name;
|
||||
if AProps.Font.Size <> '' then Font.Size := AProps.Font.Size;
|
||||
if AProps.Font.Style <> cfsNormal then Font.Style := AProps.Font.Style;
|
||||
if AProps.Font.Weight <> cfwNormal then Font.Weight := AProps.Font.Weight;
|
||||
|
||||
if AProps.MarginBottom.Style <> cmsNone then
|
||||
FMarginBottom.Style := AProps.MarginBottom.Style;
|
||||
if AProps.MarginBottom.Size <> 0 then
|
||||
FMarginBottom.Size := AProps.MarginBottom.Size;
|
||||
|
||||
if AProps.MarginLeft.Style <> cmsNone then
|
||||
FMarginLeft.Style := AProps.MarginLeft.Style;
|
||||
if AProps.MarginLeft.Size <> 0 then
|
||||
FMarginLeft.Size := AProps.MarginLeft.Size;
|
||||
|
||||
if AProps.MarginRight.Style <> cmsNone then
|
||||
FMarginRight.Style := AProps.MarginRight.Style;
|
||||
if AProps.MarginRight.Size <> 0 then
|
||||
FMarginRight.Size := AProps.MarginRight.Size;
|
||||
|
||||
if AProps.MarginTop.Style <> cmsNone then
|
||||
FMarginTop.Style := AProps.MarginTop.Style;
|
||||
if AProps.MarginTop.Size <> 0 then
|
||||
FMarginTop.Size := AProps.MarginTop.Size;
|
||||
|
||||
if AProps.Width.LengthType <> cltUndefined then
|
||||
FWidth := AProps.Width;
|
||||
end;
|
||||
|
||||
|
||||
{ TCSSGlobalProps }
|
||||
|
||||
constructor TCSSGlobalProps.Create;
|
||||
begin
|
||||
FElements := TFPObjectHashTable.Create(True);
|
||||
end;
|
||||
|
||||
destructor TCSSGlobalProps.Destroy;
|
||||
begin
|
||||
FElements.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
{$IFDEF IP_LAZARUS_DBG}
|
||||
procedure TCSSGlobalProps.DoDumpProps(Item: TObject; const Key: String; var Continue: Boolean);
|
||||
var
|
||||
lProp: TCSSProps;
|
||||
begin
|
||||
lProp := TCSSProps(Item);
|
||||
WriteLn('CSS for >>>: ', Key);
|
||||
WriteLn(' Color : ', lProp.Color);
|
||||
WriteLn(' BgColor : ', lProp.BGColor);
|
||||
WriteLn(' Font : ', lProp.Font.Name, ':', lProp.Font.FFamily, ':', lProp.Font.Size);
|
||||
WriteLn(' Align : ' + GetEnumName(TypeInfo(TIpHtmlAlign), ord(lProp.Alignment)));
|
||||
end;
|
||||
|
||||
procedure TCSSGlobalProps.DumpProps;
|
||||
begin
|
||||
FElements.Iterate(DoDumpProps);
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
function TCSSGlobalProps.GetPropsObject(ATagName: String;
|
||||
AClassID: String; CreateIfNotExist: Boolean): TCSSProps;
|
||||
var
|
||||
Selector: String;
|
||||
|
||||
procedure Lookup(const AName: String);
|
||||
begin
|
||||
if length(AClassID) > 0 then
|
||||
{$IFDEF CSS_CASESENSITIVE_CLASSID}
|
||||
Selector := AName + '.' + AClassID
|
||||
{$ELSE}
|
||||
Selector := AName + '.' + Lowercase(AClassID)
|
||||
{$ENDIF}
|
||||
else
|
||||
Selector := AName;
|
||||
|
||||
// The css selectors are already lowercase, this is
|
||||
// already done in the css parser. And the html parser
|
||||
// can only deliver its own built-in tag names anyways.
|
||||
// Also the names are not expected to be longer than
|
||||
// ShortString (this would need to be a ridiculously
|
||||
// long ClassID), should this ever happen then
|
||||
// it would be silently truncated in the following
|
||||
// type conversion to ShortString.
|
||||
Result := TCSSProps(FElements.Items[Selector]);
|
||||
end;
|
||||
|
||||
begin
|
||||
Result := nil;
|
||||
if (length(AClassID) = 0) and (length(ATagName) = 0) then
|
||||
exit;
|
||||
|
||||
Lookup(ATagName);
|
||||
if (Result=nil) and not CreateIfNotExist then
|
||||
Lookup('*');
|
||||
|
||||
if (Result = nil) and CreateIfNotExist then
|
||||
begin
|
||||
Result := TCSSProps.Create;
|
||||
FElements.Add(Selector, Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ TCSSBorder }
|
||||
|
||||
constructor TCSSBorder.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
FWidth := -1;
|
||||
FColor := clBlack;
|
||||
FStyle := cbsNone;
|
||||
end;
|
||||
|
||||
end.
|
||||
end.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ interface
|
||||
|
||||
uses
|
||||
types, Classes, SysUtils, LCLPRoc, LCLIntf, Graphics,
|
||||
IpUtils, IpHtml, iphtmlprop;
|
||||
IpUtils, IpHtml, IpHtmlProp, IpHtmlUtils;
|
||||
|
||||
type
|
||||
|
||||
|
3060
components/turbopower_ipro/iphtmlparser.pas
Normal file
3060
components/turbopower_ipro/iphtmlparser.pas
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
unit iphtmlprop;
|
||||
unit IpHtmlProp;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
|
592
components/turbopower_ipro/iphtmlutils.pas
Normal file
592
components/turbopower_ipro/iphtmlutils.pas
Normal file
@ -0,0 +1,592 @@
|
||||
unit IpHtmlUtils;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Graphics,
|
||||
IpHtmlProp;
|
||||
|
||||
const
|
||||
ShyChar = #1; {character used to represent soft-hyphen in strings}
|
||||
NbspChar = #2; {character used to represent no-break space in strings}
|
||||
NAnchorChar = #3 ; {character used to represent an Anchor }
|
||||
NbspUtf8 = #194#160; {utf8 code of no-break space character}
|
||||
LF = #10;
|
||||
CR = #13;
|
||||
|
||||
function ColorFromString(S: String): TColor;
|
||||
function TryColorFromString(S: String; out AColor: TColor; out AErrMsg: String): Boolean;
|
||||
|
||||
function GetAlignmentForStr(S: string; ADefault: TIpHtmlAlign = haDefault): TIpHtmlAlign;
|
||||
|
||||
function EscapeToAnsi(const S: string): string;
|
||||
//procedure TrimFormatting(const S: string; Target: PAnsiChar; PreFormatted: Boolean = False);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Translations, LazUTF8,
|
||||
IpConst,IpUtils;
|
||||
|
||||
const
|
||||
htmlNamedColors: array[0..140] of record
|
||||
s: string;
|
||||
c: TColor;
|
||||
end = ( // alphabetically ordered
|
||||
(s:'ALICEBLUE'; c:$FFF8F0),
|
||||
(s:'ANTIQUEWHITE'; c:$D7EBFA),
|
||||
(s:'AQUA'; c: $FFFF00),
|
||||
(s:'AQUAMARINE'; c:$D4FF7F),
|
||||
(s:'AZURE'; c:$FFFFF0),
|
||||
(s:'BEIGE'; c:$DCF5F5),
|
||||
(s:'BISQUE'; c:$C4E4FF),
|
||||
(s:'BLACK'; c:clBlack),
|
||||
(s:'BLANCHEDALMOND'; c:$CDEBFF),
|
||||
(s:'BLUE'; c:$FF0000),
|
||||
(s:'BLUEVIOLET'; c:$E22B8A),
|
||||
(s:'BROWN'; c:$2A2AA5),
|
||||
(s:'BURLYWOOD'; c:$87B8DE),
|
||||
(s:'CADETBLUE'; c:$A09E5F),
|
||||
(s:'CHARTREUSE'; c:$00FF7F),
|
||||
(s:'CHOCOLATE'; c:$1E69D2),
|
||||
(s:'CORAL'; c:$507FFF),
|
||||
(s:'CORNFLOWERBLUE'; c:$ED9564),
|
||||
(s:'CORNSILK'; c:$DCF8FF),
|
||||
(s:'CRIMSON'; c:$3C14DC),
|
||||
(s:'CYAN'; c: $FFFF00),
|
||||
(s:'DARKBLUE'; c:$8B0000),
|
||||
(s:'DARKCYAN'; c:$8B8B00),
|
||||
(s:'DARKGOLDENROD'; c:$0B86B8),
|
||||
(s:'DARKGRAY'; c:$A9A9A9),
|
||||
(s:'DARKGREEN'; c:$006400),
|
||||
(s:'DARKKHAKI'; c:$6BB7BD),
|
||||
(s:'DARKMAGENTA'; c:$8B008B),
|
||||
(s:'DARKOLIVEGREEN'; c:$2F6B55),
|
||||
(s:'DARKORANGE'; c:$008CFF),
|
||||
(s:'DARKORCHID'; c:$CC3299),
|
||||
(s:'DARKRED'; c:$00008B),
|
||||
(s:'DARKSALMON'; c:$7A96E9),
|
||||
(s:'DARKSEAGREEN'; c:$8FBC8F),
|
||||
(s:'DARKSLATEBLUE' ; c:$8B3D48),
|
||||
(s:'DARKSLATEGRAY'; c:$4F4F2F),
|
||||
(s:'DARKTURQUOISE'; c:$D1CE00),
|
||||
(s:'DARKVIOLET'; c:$D30094),
|
||||
(s:'DARKYELLOW'; c:$008080),
|
||||
(s:'DEEPPINK'; c:$9314FF),
|
||||
(s:'DEEPSKYBLUE'; c:$FFBF00),
|
||||
(s:'DIMGRAY'; c:$696969),
|
||||
(s:'DODGERBLUE'; c:$FF901E),
|
||||
(s:'FIREBRICK'; c:$2222B2),
|
||||
(s:'FLORALWHITE'; c:$F0FAFF),
|
||||
(s:'FORESTGREEN'; c:$228B22),
|
||||
(s:'FUCHSIA'; c:$FF00FF),
|
||||
(s:'GAINSBORO'; c:$DCDCDC),
|
||||
(s:'GHOSTWHITE'; c:$FFF8F8),
|
||||
(s:'GOLD'; c:$00D7FF),
|
||||
(s:'GOLDENROD'; c:$20A5DA),
|
||||
(s:'GRAY'; c:$808080),
|
||||
(s:'GREEN'; c:$008000),
|
||||
(s:'GREENYELLOW'; c:$2FFFAD),
|
||||
(s:'HONEYDEW'; c:$F0FFF0),
|
||||
(s:'HOTPINK'; c:$B469FF),
|
||||
(s:'INDIANRED'; c:$5C5CCD),
|
||||
(s:'INDIGO'; c:$82004B),
|
||||
(s:'IVORY'; c:$F0FFFF),
|
||||
(s:'KHAKI'; c:$8CE6F0),
|
||||
(s:'LAVENDER'; c:$FAE6E6),
|
||||
(s:'LAVENDERBLUSH'; c:$F5F0FF),
|
||||
(s:'LAWNGREEN'; c:$00FC7C),
|
||||
(s:'LEMONCHIFFON'; c:$CDFAFF),
|
||||
(s:'LIGHTBLUE'; c:$E6D8AD),
|
||||
(s:'LIGHTCORAL'; c:$8080F0),
|
||||
(s:'LIGHTCYAN'; c:$FFFFE0),
|
||||
(s:'LIGHTGOLDENRODYELLOW'; c:$D2FAFA),
|
||||
(s:'LIGHTGREEN'; c:$90EE90),
|
||||
(s:'LIGHTGREY'; c:$D3D3D3),
|
||||
(s:'LIGHTPINK'; c:$C1B6FF),
|
||||
(s:'LIGHTSALMON'; c:$7AA0FF),
|
||||
(s:'LIGHTSEAGREEN'; c:$AAB220),
|
||||
(s:'LIGHTSKYBLUE'; c:$FACE87),
|
||||
(s:'LIGHTSLATEGRAY'; c:$998877),
|
||||
(s:'LIGHTSTEELBLUE'; c:$DEC4B0),
|
||||
(s:'LIGHTYELLOW'; c:$E0FFFF),
|
||||
(s:'LIME'; c:$00FF00),
|
||||
(s:'LIMEGREEN'; c:$32CD32),
|
||||
(s:'LINEN'; c:$E6F0FA),
|
||||
(s:'MAGENTA'; c:$FF00FF),
|
||||
(s:'MAROON'; c:$000080),
|
||||
(s:'MEDIUMAQUAMARINE'; c:$AACD66),
|
||||
(s:'MEDIUMBLUE'; c:$CD0000),
|
||||
(s:'MEDIUMORCHID'; c:$D355BA),
|
||||
(s:'MEDIUMPURPLE'; c:$DB7093),
|
||||
(s:'MEDIUMSEAGREEN'; c:$71B33C),
|
||||
(s:'MEDIUMSLATEBLUE'; c:$EE687B),
|
||||
(s:'MEDIUMSPRINGGREEN'; c:$9AFA00),
|
||||
(s:'MEDIUMTURQUOISE'; c:$CCD148),
|
||||
(s:'MEDIUMVIOLETRED'; c:$8515C7),
|
||||
(s:'MIDNIGHTBLUE'; c:$701919),
|
||||
(s:'MINTCREAM'; c:$FAFFF5),
|
||||
(s:'MISTYROSE'; c:$E1E4FF),
|
||||
(s:'MOCCASIN'; c:$B5E4FF),
|
||||
(s:'NAVAJOWHITE'; c:$ADDEFF),
|
||||
(s:'NAVY'; c:$800000),
|
||||
(s:'OLDLACE'; c:$E6F5FD),
|
||||
(s:'OLIVE'; c:$008080),
|
||||
(s:'OLIVEDRAB'; c:$238E6B),
|
||||
(s:'ORANGE'; c:$00A5FF),
|
||||
(s:'ORANGERED'; c:$0045FF),
|
||||
(s:'ORCHID'; c:$D670DA),
|
||||
(s:'PALEGOLDENROD'; c:$AAE8EE),
|
||||
(s:'PALEGREEN'; c:$98FB98),
|
||||
(s:'PALETURQUOISE'; c:$EEEEAF),
|
||||
(s:'PALEVIOLETRED'; c:$9370DB),
|
||||
(s:'PAPAYAWHIP'; c:$D5EFFF),
|
||||
(s:'PEACHPUFF'; c:$B9DAFF),
|
||||
(s:'PERU'; c:$3F85CD),
|
||||
(s:'PINK'; c:$CBC0FF),
|
||||
(s:'PLUM'; c:$DDA0DD),
|
||||
(s:'POWDERBLUE'; c:$E6E0B0),
|
||||
(s:'PURPLE'; c:$800080),
|
||||
(s:'RED'; c:$0000FF),
|
||||
(s:'ROSYBROWN'; c:$8F8FBC),
|
||||
(s:'ROYALBLUE'; c:$901604),
|
||||
(s:'SADDLEBROWN'; c:$13458B),
|
||||
(s:'SALMON'; c:$7280FA),
|
||||
(s:'SANDYBROWN'; c:$60A4F4),
|
||||
(s:'SEAGREEN'; c:$578B2E),
|
||||
(s:'SEASHELL'; c:$EEF5FF),
|
||||
(s:'SIENNA'; c:$2D52A0),
|
||||
(s:'SILVER'; c:$C0C0C0),
|
||||
(s:'SKYBLUE'; c:$EBCE87),
|
||||
(s:'SLATEBLUE'; c:$CD5A6A),
|
||||
(s:'SLATEGRAY'; c:$908070),
|
||||
(s:'SNOW'; c:$FAFAFF),
|
||||
(s:'SPRINGGREEN'; c:$7FFF00),
|
||||
(s:'STEELBLUE'; c:$B48246),
|
||||
(s:'TAN'; c:$8CB4D2),
|
||||
(s:'TEAL'; c:$808000),
|
||||
(s:'THISTLE'; c:$D8BFD8),
|
||||
(s:'TOMATO'; c:$4763FF),
|
||||
(s:'TURQUOISE'; c:$D0E040),
|
||||
(s:'VIOLET'; c:$EE82EE),
|
||||
(s:'WHEAT'; c:$B3DEF5),
|
||||
(s:'WHITE'; c:$FFFFFF),
|
||||
(s:'WHITESMOKE'; c:$F5F5F5),
|
||||
(s:'YELLOW'; c:$00FFFF),
|
||||
(s:'YELLOWGREEN'; c:$32CD9A)
|
||||
);
|
||||
|
||||
function BinSearchNamedColor(const AColorStr: string; var AColor: TColor): boolean;
|
||||
var
|
||||
First: Integer;
|
||||
Last: Integer;
|
||||
Pivot: Integer;
|
||||
begin
|
||||
First := Low(htmlNamedColors); //Sets the first item of the range
|
||||
Last := High(htmlNamedColors); //Sets the last item of the range
|
||||
Result := False; //Initializes the Found flag (Not found yet)
|
||||
|
||||
//If First > Last then the searched item doesn't exist
|
||||
//If the item is found the loop will stop
|
||||
while (First <= Last) {and (not Result)} do
|
||||
begin
|
||||
//Gets the middle of the selected range
|
||||
Pivot := (First + Last) div 2;
|
||||
//Compares the String in the middle with the searched one
|
||||
if htmlNamedColors[Pivot].s = AColorStr then
|
||||
begin
|
||||
Result := True;
|
||||
AColor := htmlNamedColors[Pivot].c;
|
||||
exit;
|
||||
end
|
||||
//If the Item in the middle has a bigger value than
|
||||
//the searched item, then select the first half
|
||||
else if htmlNamedColors[Pivot].s > AColorStr then
|
||||
Last := Pivot - 1
|
||||
//else select the second half
|
||||
else
|
||||
First := Pivot + 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TryColorFromString(S: String; out AColor: TColor; out AErrMsg: String): Boolean;
|
||||
var
|
||||
R, G, B, Err: Integer;
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
AColor := clNone;
|
||||
if S = '' then
|
||||
begin
|
||||
Result := true;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
S := UpperCase(S);
|
||||
if S[1] = '#' then
|
||||
begin
|
||||
if Length(S) <> 7 then
|
||||
begin
|
||||
AErrMsg := SHtmlInvColor + S;
|
||||
Result := false;
|
||||
end
|
||||
else begin
|
||||
val('$'+Copy(S,2,2), R, Err);
|
||||
if Err <> 0 then
|
||||
R := 255;
|
||||
val('$'+Copy(S,4,2), G, Err);
|
||||
if Err <> 0 then
|
||||
G := 255;
|
||||
val('$'+Copy(S,6,2), B, Err);
|
||||
if Err <> 0 then
|
||||
B := 255;
|
||||
AColor := RGBToColor(R, G, B);
|
||||
Result := true;
|
||||
end;
|
||||
end else
|
||||
if BinSearchNamedColor(S, AColor) then
|
||||
begin
|
||||
Result := true;
|
||||
exit;
|
||||
end else
|
||||
if Length(S) = 6 then
|
||||
try
|
||||
val('$'+Copy(S,1,2), R, Err);
|
||||
if Err <> 0 then
|
||||
R := 255;
|
||||
val('$'+Copy(S,3,2), G, Err);
|
||||
if Err <> 0 then
|
||||
G := 255;
|
||||
val('$'+Copy(S,5,2), B, Err);
|
||||
if Err <> 0 then
|
||||
B := 255;
|
||||
AColor := RGBToColor(R, G, B);
|
||||
Result := true;
|
||||
except
|
||||
AErrMsg := SHtmlInvColor + S;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ColorFromString(S: String): TColor;
|
||||
var
|
||||
msg: String;
|
||||
begin
|
||||
if not TryColorFromString(S, Result, msg) then
|
||||
Result := clNone;
|
||||
end;
|
||||
|
||||
function GetAlignmentForStr(S: string;
|
||||
ADefault: TIpHtmlAlign = haDefault): TIpHtmlAlign;
|
||||
begin
|
||||
S := UpperCase(S);
|
||||
if Length(S) = 0 then
|
||||
begin
|
||||
Result := ADefault;
|
||||
exit;
|
||||
end;
|
||||
|
||||
case S[1] of
|
||||
'C','M':
|
||||
if S = 'CHAR' then
|
||||
Result := haChar
|
||||
else if (S = 'CENTER') or (S = 'MIDDLE') then
|
||||
Result := haCenter;
|
||||
'J':
|
||||
if S = 'JUSTIFY' then Result := haJustify;
|
||||
'L':
|
||||
if (S = 'LEFT') then Result := haLeft;
|
||||
'R':
|
||||
if S = 'RIGHT' then Result := haRight;
|
||||
else
|
||||
Result := ADefault;
|
||||
end;
|
||||
end;
|
||||
|
||||
const
|
||||
CodeCount = 126;
|
||||
|
||||
{Sorted by Size where size is Length(Name).
|
||||
Make sure you respect this when adding new items}
|
||||
Codes: array[0..Pred(CodeCount)] of record
|
||||
Size: Integer;
|
||||
Name: String;
|
||||
Value: String;
|
||||
ValueUtf8: String; //UTF8 DiBo33
|
||||
end = (
|
||||
(Size: 2; Name: 'gt'; Value: '>'; ValueUtf8: #$3E),
|
||||
(Size: 2; Name: 'lt'; Value: '<'; ValueUtf8: #$3C),
|
||||
(Size: 3; Name: 'amp'; Value: '&'; ValueUtf8: #$26),
|
||||
(Size: 3; Name: 'deg'; Value: #176; ValueUtf8: #$C2#$B0),
|
||||
(Size: 3; Name: 'ETH'; Value: #208; ValueUtf8: #$C3#$90),
|
||||
(Size: 3; Name: 'eth'; Value: #240; ValueUtf8: #$C3#$B0),
|
||||
(Size: 3; Name: 'not'; Value: #172; ValueUtf8: #$C2#$AC),
|
||||
(Size: 3; Name: 'reg'; Value: #174; ValueUtf8: #$C2#$AE),
|
||||
(Size: 3; Name: 'shy'; Value: ShyChar; ValueUtf8: ShyChar),
|
||||
(Size: 3; Name: 'uml'; Value: #168; ValueUtf8: #$C2#$A8),
|
||||
(Size: 3; Name: 'yen'; Value: #165; ValueUtf8: #$C2#$A5),
|
||||
(Size: 4; Name: 'Auml'; Value: #196; ValueUtf8: #$C3#$84),
|
||||
(Size: 4; Name: 'auml'; Value: #228; ValueUtf8: #$C3#$A4),
|
||||
(Size: 4; Name: 'bull'; Value: #149; ValueUtf8: #$E2#$80#$A2),
|
||||
(Size: 4; Name: 'cent'; Value: #162; ValueUtf8: #$C2#$A2),
|
||||
(Size: 4; Name: 'circ'; Value: '^'; ValueUtf8: #$5E),
|
||||
(Size: 4; Name: 'copy'; Value: #169; ValueUtf8: #$C2#$A9),
|
||||
(Size: 4; Name: 'Euml'; Value: #203; ValueUtf8: #$C3#$8B),
|
||||
(Size: 4; Name: 'euml'; Value: #235; ValueUtf8: #$C3#$AB),
|
||||
(Size: 4; Name: 'euro'; Value: #128; ValueUtf8: #$E2#$82#$AC),
|
||||
(Size: 4; Name: 'fnof'; Value: #131; ValueUtf8: #$C6#$92),
|
||||
(Size: 4; Name: 'Iuml'; Value: #207; ValueUtf8: #$C3#$8F),
|
||||
(Size: 4; Name: 'iuml'; Value: #239; ValueUtf8: #$C3#$AF),
|
||||
(Size: 4; Name: 'macr'; Value: #175; ValueUtf8: #$C2#$AF),
|
||||
(Size: 4; Name: 'nbsp'; Value: NbspChar; ValueUtf8: NbspChar),
|
||||
(Size: 4; Name: 'ordf'; Value: #170; ValueUtf8: #$C2#$AA),
|
||||
(Size: 4; Name: 'ordm'; Value: #186; ValueUtf8: #$C2#$BA),
|
||||
(Size: 4; Name: 'Ouml'; Value: #214; ValueUtf8: #$C3#$96),
|
||||
(Size: 4; Name: 'ouml'; Value: #246; ValueUtf8: #$C3#$B6),
|
||||
(Size: 4; Name: 'para'; Value: #182; ValueUtf8: #$C2#$B6),
|
||||
(Size: 4; Name: 'quot'; Value: '"'; ValueUtf8: #$22),
|
||||
(Size: 4; Name: 'sect'; Value: #167; ValueUtf8: #$C2#$A7),
|
||||
(Size: 4; Name: 'sup1'; Value: #185; ValueUtf8: #$C2#$B9),
|
||||
(Size: 4; Name: 'sup2'; Value: #178; ValueUtf8: #$C2#$B2),
|
||||
(Size: 4; Name: 'sup3'; Value: #179; ValueUtf8: #$C2#$B3),
|
||||
(Size: 4; Name: 'Uuml'; Value: #220; ValueUtf8: #$C3#$9C),
|
||||
(Size: 4; Name: 'uuml'; Value: #252; ValueUtf8: #$C3#$BC),
|
||||
(Size: 4; Name: 'Yuml'; Value: #159; ValueUtf8: #$C5#$B8),
|
||||
(Size: 4; Name: 'yuml'; Value: #255; ValueUtf8: #$C3#$BF),
|
||||
(Size: 5; Name: 'Acirc'; Value: #194; ValueUtf8: #$C3#$82),
|
||||
(Size: 5; Name: 'acirc'; Value: #226; ValueUtf8: #$C3#$A2),
|
||||
(Size: 5; Name: 'acute'; Value: #180; ValueUtf8: #$C2#$B4),
|
||||
(Size: 5; Name: 'AElig'; Value: #198; ValueUtf8: #$C3#$86),
|
||||
(Size: 5; Name: 'aelig'; Value: #230; ValueUtf8: #$C3#$A6),
|
||||
(Size: 5; Name: 'Aring'; Value: #197; ValueUtf8: #$C3#$85),
|
||||
(Size: 5; Name: 'aring'; Value: #229; ValueUtf8: #$C3#$A5),
|
||||
(Size: 5; Name: 'cedil'; Value: #184; ValueUtf8: #$C2#$B8),
|
||||
(Size: 5; Name: 'Ecirc'; Value: #202; ValueUtf8: #$C3#$8A),
|
||||
(Size: 5; Name: 'ecirc'; Value: #234; ValueUtf8: #$C3#$AA),
|
||||
(Size: 5; Name: 'frasl'; Value: '/'; ValueUtf8: #$2F),
|
||||
(Size: 5; Name: 'Icirc'; Value: #206; ValueUtf8: #$C3#$8E),
|
||||
(Size: 5; Name: 'icirc'; Value: #238; ValueUtf8: #$C3#$AE),
|
||||
(Size: 5; Name: 'iexcl'; Value: #161; ValueUtf8: #$C2#$A1),
|
||||
(Size: 5; Name: 'laquo'; Value: #171; ValueUtf8: #$C2#$AB),
|
||||
(Size: 5; Name: 'ldquo'; Value: #147; ValueUtf8: #$E2#$80#$9C),
|
||||
(Size: 5; Name: 'lsquo'; Value: #145; ValueUtf8: #$E2#$80#$98),
|
||||
(Size: 5; Name: 'mdash'; Value: #151; ValueUtf8: #$E2#$80#$94),
|
||||
(Size: 5; Name: 'micro'; Value: #181; ValueUtf8: #$C2#$B5),
|
||||
(Size: 5; Name: 'minus'; Value: '-'; ValueUtf8: #$2D),
|
||||
(Size: 5; Name: 'ndash'; Value: #150; ValueUtf8: #$E2#$80#$93),
|
||||
(Size: 5; Name: 'Ocirc'; Value: #212; ValueUtf8: #$C3#$94),
|
||||
(Size: 5; Name: 'ocirc'; Value: #244; ValueUtf8: #$C3#$B4),
|
||||
(Size: 5; Name: 'OElig'; Value: #140; ValueUtf8: #$C5#$92),
|
||||
(Size: 5; Name: 'oelig'; Value: #156; ValueUtf8: #$C5#$93),
|
||||
(Size: 5; Name: 'pound'; Value: #163; ValueUtf8: #$C2#$A3),
|
||||
(Size: 5; Name: 'raquo'; Value: #187; ValueUtf8: #$C2#$BB),
|
||||
(Size: 5; Name: 'rdquo'; Value: #148; ValueUtf8: #$E2#$80#$9D),
|
||||
(Size: 5; Name: 'rsquo'; Value: #146; ValueUtf8: #$E2#$80#$99),
|
||||
(Size: 5; Name: 'szlig'; Value: #223; ValueUtf8: #$C3#$9F),
|
||||
(Size: 5; Name: 'THORN'; Value: #222; ValueUtf8: #$C3#$9E),
|
||||
(Size: 5; Name: 'thorn'; Value: #254; ValueUtf8: #$C3#$BE),
|
||||
(Size: 5; Name: 'tilde'; Value: '~'; ValueUtf8: #$7E),
|
||||
(Size: 5; Name: 'times'; Value: #215; ValueUtf8: #$C3#$97),
|
||||
(Size: 5; Name: 'trade'; Value: #153; ValueUtf8: #$E2#$84#$A2),
|
||||
(Size: 5; Name: 'Ucirc'; Value: #219; ValueUtf8: #$C3#$9B),
|
||||
(Size: 5; Name: 'ucirc'; Value: #251; ValueUtf8: #$C3#$BB),
|
||||
(Size: 6; Name: 'Aacute'; Value: #193; ValueUtf8: #$C3#$81),
|
||||
(Size: 6; Name: 'aacute'; Value: #225; ValueUtf8: #$C3#$A1),
|
||||
(Size: 6; Name: 'Agrave'; Value: #192; ValueUtf8: #$C3#$80),
|
||||
(Size: 6; Name: 'agrave'; Value: #224; ValueUtf8: #$C3#$A0),
|
||||
(Size: 6; Name: 'Atilde'; Value: #195; ValueUtf8: #$C3#$83),
|
||||
(Size: 6; Name: 'atilde'; Value: #227; ValueUtf8: #$C3#$A3),
|
||||
(Size: 6; Name: 'brvbar'; Value: #166; ValueUtf8: #$C2#$A6),
|
||||
(Size: 6; Name: 'Ccedil'; Value: #199; ValueUtf8: #$C3#$87),
|
||||
(Size: 6; Name: 'ccedil'; Value: #231; ValueUtf8: #$C3#$A7),
|
||||
(Size: 6; Name: 'curren'; Value: #164; ValueUtf8: #$C2#$A4),
|
||||
(Size: 6; Name: 'dagger'; Value: #134; ValueUtf8: #$E2#$80#$A0),
|
||||
(Size: 6; Name: 'Dagger'; Value: #135; ValueUtf8: #$E2#$80#$A1),
|
||||
(Size: 6; Name: 'divide'; Value: #247; ValueUtf8: #$C3#$B7),
|
||||
(Size: 6; Name: 'Eacute'; Value: #201; ValueUtf8: #$C3#$89),
|
||||
(Size: 6; Name: 'eacute'; Value: #233; ValueUtf8: #$C3#$A9),
|
||||
(Size: 6; Name: 'Egrave'; Value: #200; ValueUtf8: #$C3#$88),
|
||||
(Size: 6; Name: 'egrave'; Value: #232; ValueUtf8: #$C3#$A8),
|
||||
(Size: 6; Name: 'frac12'; Value: #189; ValueUtf8: #$C2#$BD),
|
||||
(Size: 6; Name: 'frac14'; Value: #188; ValueUtf8: #$C2#$BC),
|
||||
(Size: 6; Name: 'frac34'; Value: #190; ValueUtf8: #$C2#$BE),
|
||||
(Size: 6; Name: 'hellip'; Value: #133; ValueUtf8: #$E2#$80#$A6),
|
||||
(Size: 6; Name: 'Iacute'; Value: #205; ValueUtf8: #$C3#$8D),
|
||||
(Size: 6; Name: 'iacute'; Value: #237; ValueUtf8: #$C3#$AD),
|
||||
(Size: 6; Name: 'Igrave'; Value: #204; ValueUtf8: #$C3#$8C),
|
||||
(Size: 6; Name: 'igrave'; Value: #236; ValueUtf8: #$C3#$AC),
|
||||
(Size: 6; Name: 'iquest'; Value: #191; ValueUtf8: #$C2#$BF),
|
||||
(Size: 6; Name: 'lsaquo'; Value: #139; ValueUtf8: #$E2#$80#$B9),
|
||||
(Size: 6; Name: 'middot'; Value: #183; ValueUtf8: #$C2#$B7),
|
||||
(Size: 6; Name: 'Ntilde'; Value: #209; ValueUtf8: #$C3#$91),
|
||||
(Size: 6; Name: 'ntilde'; Value: #241; ValueUtf8: #$C3#$B1),
|
||||
(Size: 6; Name: 'Oacute'; Value: #211; ValueUtf8: #$C3#$93),
|
||||
(Size: 6; Name: 'oacute'; Value: #243; ValueUtf8: #$C3#$B3),
|
||||
(Size: 6; Name: 'Ograve'; Value: #210; ValueUtf8: #$C3#$92),
|
||||
(Size: 6; Name: 'ograve'; Value: #242; ValueUtf8: #$C3#$B2),
|
||||
(Size: 6; Name: 'Oslash'; Value: #216; ValueUtf8: #$C3#$98),
|
||||
(Size: 6; Name: 'oslash'; Value: #248; ValueUtf8: #$C3#$B8),
|
||||
(Size: 6; Name: 'Otilde'; Value: #213; ValueUtf8: #$C3#$95),
|
||||
(Size: 6; Name: 'otilde'; Value: #245; ValueUtf8: #$C3#$B5),
|
||||
(Size: 6; Name: 'permil'; Value: #137; ValueUtf8: #$E2#$80#$B0),
|
||||
(Size: 6; Name: 'plusmn'; Value: #177; ValueUtf8: #$C2#$B1),
|
||||
(Size: 6; Name: 'rsaquo'; Value: #155; ValueUtf8: #$E2#$80#$BA),
|
||||
(Size: 6; Name: 'Scaron'; Value: #138; ValueUtf8: #$C5#$A0),
|
||||
(Size: 6; Name: 'scaron'; Value: #154; ValueUtf8: #$C5#$A1),
|
||||
(Size: 6; Name: 'Uacute'; Value: #218; ValueUtf8: #$C3#$9A),
|
||||
(Size: 6; Name: 'uacute'; Value: #250; ValueUtf8: #$C3#$BA),
|
||||
(Size: 6; Name: 'Ugrave'; Value: #217; ValueUtf8: #$C3#$99),
|
||||
(Size: 6; Name: 'ugrave'; Value: #249; ValueUtf8: #$C3#$B9),
|
||||
(Size: 6; Name: 'Yacute'; Value: #221; ValueUtf8: #$C3#$9D),
|
||||
(Size: 6; Name: 'yacute'; Value: #253; ValueUtf8: #$C3#$BD),
|
||||
(Size: 6; Name: 'xxxxxx'; Value: NAnchorChar; ValueUtf8: NAnchorChar)
|
||||
);
|
||||
|
||||
function ParseConstant(const S: string; OnUtf8: boolean = false): string;
|
||||
var
|
||||
Error: Integer;
|
||||
Index1: Integer;
|
||||
Index2: Integer;
|
||||
Size1: Integer;
|
||||
Found: Boolean;
|
||||
begin {'Complete boolean eval' must be off}
|
||||
Result := ' ';
|
||||
Size1 := Length(S);
|
||||
if Size1 = 0 then Exit;
|
||||
if (S[1] in ['$', '0'..'9']) then
|
||||
begin
|
||||
Val(S, Index1, Error);
|
||||
if (Error = 0) then
|
||||
begin
|
||||
if not OnUTF8 and (Index1 >= 32) and (Index1 <= 255) then
|
||||
Result := Chr(Index1)
|
||||
else
|
||||
begin
|
||||
Result := UnicodeToUTF8(Index1);
|
||||
if Result = NbspUTF8 then Result := NbspChar;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Index1 := 0;
|
||||
repeat
|
||||
if Size1 = Codes[Index1].Size then
|
||||
begin
|
||||
Found := True;
|
||||
Index2 := 1;
|
||||
while Index2 <= Size1 do
|
||||
begin
|
||||
if S[Index2] <> Codes[Index1].Name[Index2] then
|
||||
begin
|
||||
Found := False;
|
||||
Break;
|
||||
end;
|
||||
Inc(Index2);
|
||||
end;
|
||||
if Found then
|
||||
begin
|
||||
if OnUtf8 then
|
||||
Result := Codes[Index1].ValueUTF8
|
||||
else
|
||||
Result := Codes[Index1].Value;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
Inc(Index1);
|
||||
until (Index1 >= CodeCount) or (Codes[Index1].Size > Size1);
|
||||
end;
|
||||
end;
|
||||
|
||||
{- returns the string with & escapes expanded}
|
||||
procedure ExpandEscapes(var S: string);
|
||||
var
|
||||
i, j : Integer;
|
||||
Co : string;
|
||||
Ch : AnsiChar;
|
||||
St : string;
|
||||
begin
|
||||
i := Length(S);
|
||||
while i > 0 do begin
|
||||
if S[i] = '&' then begin
|
||||
j := i;
|
||||
while (j < length(S)) and not (S[j] in [';', ' ']) do
|
||||
Inc(j);
|
||||
Co := copy(S, i + 1, j - i - 1);
|
||||
if Co <> '' then begin
|
||||
if Co[1] = '#' then begin
|
||||
Delete(Co, 1, 1);
|
||||
if UpCase(Co[1]) = 'X' then begin
|
||||
Delete(Co, 1, 1);
|
||||
Insert('$', Co, 1);
|
||||
end;
|
||||
end;
|
||||
Delete(S, i, j - i + 1);
|
||||
if SystemCharSetIsUTF8 then begin
|
||||
St := ParseConstant(Co, true);
|
||||
Insert(St, S, i)
|
||||
end else begin
|
||||
Ch := ParseConstant(Co)[1];
|
||||
Insert(Ch, S, i);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Dec(i);
|
||||
end;
|
||||
end;
|
||||
|
||||
function EscapeToAnsi(const S: string): string;
|
||||
var
|
||||
P : Integer;
|
||||
begin
|
||||
Result := S;
|
||||
P := CharPos('&', S);
|
||||
if P <> 0 then
|
||||
ExpandEscapes(Result);
|
||||
end;
|
||||
(*
|
||||
procedure TrimFormatting(const S: string; Target: PAnsiChar; PreFormatted: Boolean = False);
|
||||
var
|
||||
r, w: Integer;
|
||||
|
||||
procedure CopyChar(ch: AnsiChar);
|
||||
begin
|
||||
Target[w] := ch;
|
||||
Inc(w);
|
||||
end;
|
||||
|
||||
begin
|
||||
r := 1;
|
||||
w := 0;
|
||||
while r <= Length(S) do begin
|
||||
case S[r] of
|
||||
#0..#8, #11..#12, #14..#31 :
|
||||
;
|
||||
#9 :
|
||||
if PreFormatted then
|
||||
CopyChar(' ');
|
||||
#13 :
|
||||
if PreFormatted then
|
||||
CopyChar(LF);
|
||||
#10 :
|
||||
if PreFormatted then begin
|
||||
if (w = 0) or (Target[w-1] <> LF) then
|
||||
CopyChar(LF);
|
||||
end
|
||||
else begin
|
||||
if w > 1 then
|
||||
CopyChar(' ');
|
||||
end;
|
||||
' ' :
|
||||
if PreFormatted or (w = 0) or (Target[w-1] <> ' ') then
|
||||
CopyChar(' ');
|
||||
else
|
||||
CopyChar(S[r]);
|
||||
end;
|
||||
Inc(r);
|
||||
end;
|
||||
Target[w] := #0;
|
||||
end; *)
|
||||
|
||||
end.
|
||||
|
@ -273,6 +273,54 @@ const
|
||||
'</body>' + LE +
|
||||
'</html>';
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CSS
|
||||
//------------------------------------------------------------------------------
|
||||
const
|
||||
HTMLCommentInCSS_title =
|
||||
'HTML comment in CSS section';
|
||||
HTMLCommentInCSS_descr =
|
||||
'The text must be red.';
|
||||
HTMLCommentInCSS_html =
|
||||
'<html>' + LE +
|
||||
'<head>' + LE +
|
||||
' <style type="text/css">' + LE +
|
||||
' <!--' + LE +
|
||||
' body { color: red; }' + LE +
|
||||
' -->' + LE +
|
||||
' </style>' + LE +
|
||||
'</head>' + LE +
|
||||
'<body>' + LE +
|
||||
' <p>abc</p>' + LE +
|
||||
'</body>' + LE +
|
||||
'</html>';
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Special cases in file structure
|
||||
//------------------------------------------------------------------------------
|
||||
const
|
||||
NoHtmlTag_title =
|
||||
'No <html> tag';
|
||||
NoHtmlTag_descr =
|
||||
'You should see an ordered list with two items "line 1" and "line 2".';
|
||||
NoHtmlTag_html =
|
||||
'<body>' + LE +
|
||||
' <ol>' + LE +
|
||||
' <li>line 1</li>' + LE +
|
||||
' <li>line 2</li>' + LE +
|
||||
' </ol>' + LE +
|
||||
'</body>';
|
||||
|
||||
const
|
||||
NoBodyTag_title =
|
||||
'No <body> tag';
|
||||
NoBodyTag_descr =
|
||||
'You should see an ordered list with two items "line 1" and "line 2".';
|
||||
NoBodyTag_html =
|
||||
'<ol>' + LE +
|
||||
' <li>line 1</li>' + LE +
|
||||
' <li>line 2</li>' + LE +
|
||||
'</ol>';
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -139,7 +139,7 @@ end;
|
||||
|
||||
procedure TForm1.PopulateTests;
|
||||
var
|
||||
node: TTreeNode;
|
||||
node, node1: TTreeNode;
|
||||
begin
|
||||
TreeView1.Items.BeginUpdate;
|
||||
try
|
||||
@ -162,11 +162,22 @@ begin
|
||||
AddTest(node, TextInColoredTableCell_title, TextInColoredTableCell_descr, TextInColoredTableCell_html);
|
||||
node.Expanded := true;
|
||||
|
||||
node := TreeView1.Items.AddChild(nil, 'Text alignment');
|
||||
AddTest(node, AlignInCell_title, AlignInCell_descr, AlignInCell_html);
|
||||
AddTest(node, AlignInCellBold_title, AlignInCellBold_descr, AlignInCellBold_html);
|
||||
AddTest(node, AlignInCell_CSS_title, AlignInCell_CSS_descr, AlignInCell_CSS_html);
|
||||
AddTest(node, AlignInCellBold_CSS_title, AlignInCellBold_CSS_descr, AlignInCellBold_CSS_html);
|
||||
node := TreeView1.Items.AddChild(nil, 'Tables');
|
||||
node1 := TreeView1.Items.AddChild(node, 'Text alignment');
|
||||
AddTest(node1, AlignInCell_title, AlignInCell_descr, AlignInCell_html);
|
||||
AddTest(node1, AlignInCellBold_title, AlignInCellBold_descr, AlignInCellBold_html);
|
||||
AddTest(node1, AlignInCell_CSS_title, AlignInCell_CSS_descr, AlignInCell_CSS_html);
|
||||
AddTest(node1, AlignInCellBold_CSS_title, AlignInCellBold_CSS_descr, AlignInCellBold_CSS_html);
|
||||
node1.Expanded := true;
|
||||
node.Expanded := true;
|
||||
|
||||
node := TreeView1.Items.AddChild(nil, 'CSS');
|
||||
AddTest(node, HTMLCommentInCSS_title, HTMLCommentInCSS_descr, HTMLCommentInCSS_html);
|
||||
node.Expanded := true;
|
||||
|
||||
node := TreeView1.Items.AddChild(nil, 'Special cases in file structure');
|
||||
AddTest(node, NoHtmlTag_title, NoHtmlTag_descr, NoHtmlTag_html);
|
||||
AddTest(node, NoBodyTag_title, NoBodyTag_descr, NoBodyTag_html);
|
||||
node.Expanded := true;
|
||||
|
||||
finally
|
||||
|
@ -25,7 +25,7 @@
|
||||
<License Value="MPL - Mozilla public license
|
||||
"/>
|
||||
<Version Major="1"/>
|
||||
<Files Count="17">
|
||||
<Files Count="20">
|
||||
<Item1>
|
||||
<Filename Value="ipanim.pas"/>
|
||||
<UnitName Value="IpAnim"/>
|
||||
@ -98,6 +98,18 @@
|
||||
<Filename Value="iphtmlgenerated.inc"/>
|
||||
<Type Value="Binary"/>
|
||||
</Item17>
|
||||
<Item18>
|
||||
<Filename Value="iphtmlparser.pas"/>
|
||||
<UnitName Value="IpHtmlParser"/>
|
||||
</Item18>
|
||||
<Item19>
|
||||
<Filename Value="iphtmlutils.pas"/>
|
||||
<UnitName Value="IpHtmlUtils"/>
|
||||
</Item19>
|
||||
<Item20>
|
||||
<Filename Value="ipcss.pas"/>
|
||||
<UnitName Value="IpCSS"/>
|
||||
</Item20>
|
||||
</Files>
|
||||
<CompatibilityMode Value="True"/>
|
||||
<i18n>
|
||||
|
@ -10,7 +10,7 @@ interface
|
||||
uses
|
||||
IpAnim, IpConst, Ipfilebroker, Iphttpbroker, IpHtml, IpMsg, IpStrms,
|
||||
IpUtils, IpHtmlTabList, iphtmlprop, ipHtmlBlockLayout, ipHtmlTableLayout,
|
||||
LazarusPackageIntf;
|
||||
IpHtmlParser, IpHtmlUtils, IpCSS, LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
@ -24,4 +24,3 @@ end;
|
||||
initialization
|
||||
RegisterPackage('TurboPowerIPro', @Register);
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user