unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ValEdit, EditBtn;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
FileNameEdit1: TFileNameEdit;
Label1: TLabel;
Label2: TLabel;
ListBox1: TListBox;
ValueListEditor1: TValueListEditor;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
procedure LoadCSSClasses(aFileName: String);
procedure LoadCSSClassProperties(aClassName, aFileName: String);
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
uses
fgl, fpcssparser, fpcssscanner, fpcsstree;
type
TKeyValList = specialize TFPGMap<String, String>;
{ TClassVisitor }
TClassVisitor = Class(TCSSTreeVisitor)
private
FList: TStrings;
public
constructor Create(aList: TStrings);
procedure Visit(csse: TCSSElement); override;
end;
{ TPropertiesVisitor }
TPropertiesVisitor = Class(TCSSTreeVisitor)
private
FList: TKeyValList;
FClassName: String;
FSubClass: String;
FInClass: Boolean;
FInSubClass: Boolean;
FCurrClass: String;
FCurrSubclass: String;
public
constructor Create(aList: TKeyValList; aClassName: String);
procedure Visit(csse: TCSSElement); override;
end;
{ TClassVisitor }
constructor TClassVisitor.Create(aList: TStrings);
begin
FList := aList;
end;
procedure TClassVisitor.Visit(csse: TCSSElement);
begin
if csse.CSSType = csstClassname then
FList.Add(csse.AsString);
if csse.CSSType = csstPseudoClass then
FList[FList.Count - 1] := FList[FList.Count - 1] + csse.AsString;
end;
{ TPropertiesVisitor }
constructor TPropertiesVisitor.Create(aList: TKeyValList; aClassName: String);
var
carr: TStringArray;
begin
FClassName := '';
FSubClass := '';
FList := aList;
carr := aClassName.Split([':'], TStringSplitOptions.ExcludeEmpty);
if Length(carr) > 0 then
FClassName := carr[0];
if Length(carr) > 1 then
FSubClass := carr[1];
FInClass := False;
FInSubClass := False;
FCurrClass := '';
FCurrSubclass := '';
end;
procedure TPropertiesVisitor.Visit(csse: TCSSElement);
begin
if csse.CSSType = csstClassname then
begin
FCurrClass := csse.AsString;
FInClass := FCurrClass = FClassName;
if FSubClass = '' then
FInSubClass := True
else
FInSubClass := False;
end;
if FInClass and (csse.CSSType = csstPseudoClass) then
begin
FCurrSubClass := csse.AsString;
FInSubClass := FCurrSubclass = FSubClass;
end;
if FInClass and FInSubClass and (csse.CSSType = csstIdentifier) and ((csse.AsString + ' :') = Copy(csse.Parent.AsString, 1, Length((csse.AsString + ' :')))) then
FList.Add(csse.AsString)
else if FInClass and FInSubClass and ((csse.CSSType = csstIdentifier) or (csse.CSSType = csstIdentifier) or (csse.CSSType = csstInteger) or (csse.CSSType = csstString) or (csse.CSSType = csstFloat)) and
(csse.Parent.AsString <> FClassName) then
FList.Data[FList.Count - 1] := Trim(FList.Data[FList.Count - 1]) + ' ' + csse.AsFormattedString;
end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
if not FileExists(FileNameEdit1.FileName) then
begin
ShowMessage('Select correct file!');
exit;
end;
LoadCSSClasses(FileNameEdit1.FileName);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FileNameEdit1.DefaultExt := '.css';
FileNameEdit1.Filter := 'CSS file|*.css';
end;
procedure TForm1.ListBox1Click(Sender: TObject);
begin
LoadCSSClassProperties(ListBox1.Items[ListBox1.ItemIndex], FileNameEdit1.FileName);
end;
procedure TForm1.LoadCSSClasses(aFileName: String);
var
fs: TFileStream;
cssp : TCSSParser;
csse : TCSSElement;
cv: TClassVisitor;
sl: TStringList;
i: Integer;
begin
ListBox1.Items.BeginUpdate;
ListBox1.Items.Clear;
sl := TStringList.Create;
fs := TFileStream.Create(aFileName, fmOpenRead);
cssp := TCSSParser.Create(fs, []);
try
csse := cssp.Parse;
cv := TClassVisitor.Create(sl);
try
csse.Iterate(cv);
finally
cv.Free;
end;
for i := 0 to sl.Count - 1 do
ListBox1.Items.Add(sl[i]);
finally
csse.Free;
cssp.Free;
fs.Free;
sl.Free;
ListBox1.Items.EndUpdate;
end;
end;
procedure TForm1.LoadCSSClassProperties(aClassName, aFileName: String);
var
fs: TFileStream;
cssp : TCSSParser;
csse : TCSSElement;
pv: TPropertiesVisitor;
kvl: TKeyValList;
i: Integer;
begin
ValueListEditor1.BeginUpdate;
ValueListEditor1.RowCount := 1;
kvl := TKeyValList.Create;
fs := TFileStream.Create(aFileName, fmOpenRead);
cssp := TCSSParser.Create(fs, []);
try
csse := cssp.Parse;
pv := TPropertiesVisitor.Create(kvl, aClassName);
try
csse.Iterate(pv);
finally
pv.Free;
end;
ValueListEditor1.RowCount := kvl.Count + 1;
for i := 0 to kvl.Count - 1 do
begin
ValueListEditor1.Keys[i + 1] := kvl.Keys[i];
ValueListEditor1.Values[kvl.Keys[i]] := kvl.Data[i];
end;
finally
csse.Free;
cssp.Free;
fs.Free;
kvl.Free;
ValueListEditor1.EndUpdate;
end;
end;
end.