{TO-DO - What if I don't call .Free() on a .Create() stuff? Memory leak, or gets destroyed after function returns? - FTP } unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, OleCtrls, ExtCtrls, StrUtils; type TForm1 = class(TForm) ListBox1: TListBox; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation uses RegExpr; const inputdir : String = '.\input\'; templatesdir : String = '.\templates\'; outputdir : String = '.\output\'; datafile : String = '.\data.txt'; {$R *.dfm} //======================================================================== {function GetFileDate(TheFileName: string): string; var f: integer; begin f := FileOpen(TheFileName, 0); try //Result := DateTimeToStr(FileDateToDateTime(FileGetDate(f))); Result := DateToStr(FileDateToDateTime(FileGetDate(f))); finally FileClose(f); end; end;} function GetFileDate(TheFileName: string): TDateTime; var f: integer; begin f := FileOpen(TheFileName, 0); try Result := FileDateToDateTime(FileGetDate(f)); finally FileClose(f); end; end; procedure WriteFile (const MyFile: String; const MyStuff: String); var MyFileHdl : TextFile; begin AssignFile(MyFileHdl, MyFile); ReWrite(MyFileHdl); Write(MyFileHdl,MyStuff); CloseFile(MyFileHdl); end; { procedure ReadFileStream(const MyFile: String); var TempStream : TMemoryStream; MyStuff : String; begin TempStream := TMemoryStream.Create; MyStuff := LoadFromStream(TempStream); TempStream.Free; end; } function ReadFile (const MyFile: String): String; var MyFileHdl : TextFile; MyStuff : String; text : String; begin AssignFile(MyFileHdl, MyFile); Reset(MyFileHdl); while not Eof(MyFileHdl) do begin ReadLn(MyFileHdl, text); MyStuff := MyStuff + text + #13#10; end; CloseFile(MyFileHdl); Result := MyStuff; end; //======================================================================== procedure TForm1.Button1Click(Sender: TObject); const running : Boolean = False; //True = Already clicked var searchResult : TSearchRec; MyHeader : String; MyFooter : String; MyArticle : String; MyStuff : String; MyTitle : String; MyIndexB4 : String; MyIndexAfter : String; subdirectories : TStringList; i : Integer; OrigDate : TDateTime; CurrentDate : TDateTime; f: integer; filedata : TStringList; MyKeywords : String; MyClassification : String; MyFile : String; indexclassifications : TStringList; data : TStringList; LastModified : String; begin {MyHeader := ReadFile(templatesdir + 'header.html'); //Change TITLE in header.html to actual TITLE for this document MyTitle := 'coucou'; MyStuff := 'sqdfjqdjf'; MyStuff := ReplaceRegExpr ('.*?', MyStuff, '' + MyTitle + ''); ShowMessage(MyStuff); Exit; } { MyStuff := ''; with TRegExpr.Create do begin Expression := ''; //Replace(MyStuff,'',True); ShowMessage(ReplaceRegExpr ('', MyStuff, '')); Free; end; Exit; } { data := TStringList.Create; data.Add('key=value'); for i := 0 to data.Count - 1 do begin ShowMessage(data[i] + #13#10 + data.Names[i] + #13#10 + data.ValueFromIndex[i]); end; data.Free; Exit; } //If app already ran, make the button Close the app If (Button1.Caption = 'Close') then begin Close; Exit; end; //Check if already running If (running) then begin running := False; Button1.Caption := 'Build Site'; ListBox1.Clear; ListBox1.Items.Add('Hit Cancel: Stopping.'); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); end else begin running := True; Button1.Caption := 'Cancel'; ListBox1.Clear; ListBox1.Items.Add('Started work @ ' + TimeToStr(Time)); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); end; //Check that directories exist if not DirectoryExists(inputdir) then begin Button1.Caption := 'Build Site'; ListBox1.Clear; ListBox1.Items.Add(inputdir + ' does not exist'); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); Exit; end; if not DirectoryExists(templatesdir) then begin Button1.Caption := 'Build Site'; ListBox1.Clear; ListBox1.Items.Add(templatesdir + ' does not exist'); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); Exit; end; If not DirectoryExists(outputdir) then begin CreateDir(outputdir); end; //If exists, read .\data.txt which is used to hold TITLE and CAT for all .\output HTML files data := TStringList.Create; if FileExists(datafile) then begin data.LoadFromFile(datafile); //Set file to empty in case we make any change before rewriting to the file with SaveToFile() DeleteFile(datafile); //Deleting datafile triggers regeneration of site end else begin FindFirst(outputdir + '*.htm?', faAnyFile+faReadOnly, searchResult); DeleteFile(outputdir + searchResult.Name); while FindNext(searchResult)=0 do begin DeleteFile(outputdir + searchResult.Name); end; FindClose(searchResult); end; //======================================================================== screen.cursor:=crHourGlass; //List sub-directories if FindFirst(inputdir + '*', faDirectory, searchResult) = 0 then begin subdirectories := TStringList.Create; repeat //User clicked on Cancel? Application.ProcessMessages; if not running then begin screen.cursor := crDefault; Exit; end; // Only show directories if ((searchResult.attr and faDirectory) = faDirectory) and (searchResult.Name <> '.') and (searchResult.Name <> '..') then begin subdirectories.Add(searchResult.Name + '\'); end; until FindNext(searchResult) <> 0; // Must free up resources used by these successful finds FindClose(searchResult); end; //Check if any valid subdirectory found under .\input If subdirectories.Count = 0 then begin screen.cursor:=crHourGlass; ListBox1.Clear; ListBox1.Items.Add('No sub-directory(ies) found under ' + inputdir); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); Button1.Caption := 'Build Site'; Exit; end; //======================================================================== //Read templates MyHeader := ReadFile(templatesdir + 'header.html'); MyFooter := ReadFile(templatesdir + 'footer.html'); MyArticle := ReadFile(templatesdir + 'article.html'); for i := 0 to subdirectories.Count-1 do begin //User clicked on Cancel? Application.ProcessMessages; if not running then begin screen.cursor := crDefault; Exit; end; //Massage each file in current sub-folder if FindFirst(inputdir + subdirectories[i] + '*.htm?', faAnyFile, searchResult) = 0 then begin repeat //User clicked on Cancel? Application.ProcessMessages; if not running then begin screen.cursor := crDefault; Exit; end; //Compare FileDate in .\input and .\output: If .\input is more recent, rebuild OrigDate := GetFileDate(inputdir + subdirectories[i] + searchResult.Name); if FileExists(outputdir + searchResult.Name) then begin CurrentDate := GetFileDate(outputdir + searchResult.Name); end else begin //If file doesn't exit, set CurrentDate to dummy value; CurrentDate := 0; end; //Is .\input\ more recent that its brother in .\output, or brand new file? If (CurrentDate = 0) or (OrigDate > CurrentDate) then begin ListBox1.Items.Add('Adding/updating ' + inputdir + subdirectories[i] + searchResult.Name); MyStuff := ReadFile(inputdir + subdirectories[i] + searchResult.Name); with TRegExpr.Create do try //Make it case-insensitive ModifierI := True; Expression := '(.*?)'; if Exec (MyStuff) then begin MyTitle := Match[1]; end; //If user forgot to set TITLE... If Length(MyTitle) = 0 then begin ListBox1.Items.Add('! No TITLE found in ' + inputdir + subdirectories[i] + searchResult.Name); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); MyTitle := '(This document has no TITLE section!)'; end; Expression := ''; if Exec (MyStuff) then begin MyKeywords := Match[1] end else begin //If no keywords section, just put TITLE in there ListBox1.Items.Add('! No KEYWORDS found in ' + inputdir + subdirectories[i] + searchResult.Name); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); MyKeywords := MyTitle; end; Expression := '(.*?)'; if Exec (MyStuff) then begin MyStuff := MyHeader + MyArticle + Match[1] + MyFooter; end; //Change TITLE in header.html to actual TITLE for this document MyStuff := ReplaceRegExpr ('.*?', MyStuff, '' + MyTitle + '',True); MyClassification := AnsiLeftStr(subdirectories[i], Length(subdirectories[i]) - 1); //For subdirectory, ignore trailing '\' MyStuff := ReplaceRegExpr ('', MyStuff, //NO! Already in MyStuff above #9 + '' + MyTitle + '' + #13#10 + #9 + '' + #13#10 + #9 + '' + #13#10 + '',True); //LongDateFormat := 'dd mmmm yyyy'; DateTimeToString(LastModified, 'dd-mm-yyyy', Date); MyStuff := ReplaceRegExpr ('###date###', MyStuff, LastModified,True); WriteFile (outputdir + searchResult.Name,MyStuff); //Save infos into data file in the form myfile.html=mycategory#Some nifty title //Check if key already exists, ie. existing article was modified, not created If data.Values[searchResult.Name] <> '' then begin data.Values[searchResult.Name] := MyClassification +'#' + MyTitle; end else begin data.Add(searchResult.Name + '=' + MyClassification +'#' + MyTitle); end; finally Free; end; end else begin ListBox1.Items.Add('No change for ' + inputdir + subdirectories[i] + searchResult.Name); end; Application.ProcessMessages; //ListBox1.ItemIndex := ListBox1.Items.Count - 1; ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); until FindNext(searchResult) <> 0; // Must free up resources used by these successful finds FindClose(searchResult); end; end; //======================================================================== //Build .\output\index.html //In .\output\, delete index.html and open all other HTML files to rip their TITLE If FileExists(outputdir + 'index.html') then DeleteFile(outputdir + 'index.html'); indexclassifications := TStringList.Create; { ListBox1.Items.Add('B4 massaging HTMLs @ ' + TimeToStr(Time)); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); } { //Must check classification tag to know to which sections the document belongs if FindFirst(outputdir + '*.html', faAnyFile, searchResult) = 0 then begin repeat //User clicked on Cancel? Application.ProcessMessages; if not running then begin screen.cursor := crDefault; Exit; end; //Slows things quite a bit... MyStuff := ReadFile(outputdir + searchResult.Name); with TRegExpr.Create do try Expression := '(.*?)'; if Exec (MyStuff) then begin MyTitle := Match[1]; end; Expression := ''; if Exec (MyStuff) then begin MyClassification := Match[1]; end; indexclassifications.Values[MyClassification] := indexclassifications.Values[MyClassification] + '
  • ' + MyTitle + '
  • '; finally Free; end; Application.ProcessMessages; until FindNext(searchResult) <> 0; end; } for i := 0 to data.Count-1 do begin //Check if file was removed from .\output (we don't check but assume it's been also removed from .\input) If not FileExists(outputdir + data.Names[i]) then begin //Remove entry from data file data.Delete(i); end; end; for i := 0 to data.Count-1 do begin //User clicked on Cancel? Application.ProcessMessages; if not running then begin screen.cursor := crDefault; Exit; end; with TRegExpr.Create do try //Make it case-insensitive ModifierI := True; MyFile := data.Names[i]; Expression := '(.*?)#(.*)'; if Exec (data.ValueFromIndex[i]) then begin MyClassification := Match[1]; MyTitle := Match[2]; end; indexclassifications.Values[MyClassification] := indexclassifications.Values[MyClassification] + '
  • ' + MyTitle + '
  • ' + #13#10; finally Free; end; end; { Below! for i := 0 to indexclassifications.Count-1 do begin indexclassifications.ValueFromIndex[i] := '

    ' + indexclassifications.Names[i] + '

    ' + #13#10 + '' + #13#10; MyStuff := MyStuff + indexclassifications.ValueFromIndex[i]; end; } //===================================== { ListBox1.Items.Add('B4 creating index @ ' + TimeToStr(Time)); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); } //Let's build index.html for its constituting parts MyHeader := ReadFile(templatesdir + 'header.html'); MyFooter := ReadFile(templatesdir + 'footer.html'); MyIndexB4 := ReadFile(templatesdir + 'index-b4.html'); MyIndexAfter := ReadFile(templatesdir + 'index-after.html'); MyStuff := MyHeader + MyIndexB4; //One H3 section per classification // + AnsiUpperCase(indexclassifications.Names[i]) for i := 0 to indexclassifications.Count-1 do begin //User clicked on Cancel? Application.ProcessMessages; if not running then begin screen.cursor := crDefault; Exit; end; indexclassifications.ValueFromIndex[i] := '

    ' + indexclassifications.Names[i] + '

    ' + #13#10 + '' + #13#10; MyStuff := MyStuff + indexclassifications.ValueFromIndex[i]; Application.ProcessMessages; end; indexclassifications.Free; MyStuff := MyStuff + MyIndexAfter + MyFooter; WriteFile ('index.html',MyStuff); data.SaveToFile(datafile); data.Free; Button1.Caption := 'Build Site'; screen.cursor := crDefault; ListBox1.Items.Add('Finished work @ ' + TimeToStr(Time)); ListBox1.Perform(WM_VSCROLL, SB_BOTTOM, 0); Button1.Caption := 'Close'; running := False; end; end.