| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722 |
- unit Helpers;
- {$I ImagingOptions.inc}
- interface
- uses
- SysUtils, Classes, ImagingUtility, DemoUtils, DOM, XMLRead, XMLWrite;
- const
- sXTOCRoot = 'toc';
- sXTOCList = 'itemlist';
- sXTOCItem = 'item';
- sXName = 'name';
- sXURL = 'url';
- sXTOCFile = 'toc';
- sXTitle = 'title';
- sXRootFile = 'root';
- sXOutputFile = 'output';
- sXXslDir = 'xsldir';
- sXRefDir = 'refdir';
- SXProducer = 'producer';
- sXLinkTargetURL = 'url';
- sXLinkTargetAnchor = 'anchor';
- sXRef = 'ref';
- sXAnchorDelim = '#';
- sXTemplate = '<?xml version="1.0" encoding="utf-8"?>' + sLineBreak +
- '<?xml-stylesheet type="text/xsl" href="%s/doc2html.xsl"?>' + sLineBreak +
- '<doc>' + sLineBreak +
- ' <title>Template</title>' + sLineBreak +
- ' <chapter>' + sLineBreak +
- ' <title>Template</title>' + sLineBreak +
- ' <par>This file was autogenerated by VampyreDoc</par>' + sLineBreak +
- ' </chapter>' + sLineBreak +
- '</doc>';
- sURLDelim = '/';
- sXSLLink = 'link';
- sXSLHref = 'href';
- sXSLSrc = 'src';
- sCSSExt = 'css';
- sCSSLink = 'url';
- sCSSLinkBStart = '(';
- sCSSLinkBEnd = ')';
- type
- { Base class for objects based on elements of XML files.}
- TXMLItem = class(TObject)
- private
- FElement: TDOMElement;
- procedure ParseElement; virtual; abstract;
- function FindElement(const NodeName: string; Parent: TDOMElement;
- var Elem: TDOMElement): Boolean;
- public
- constructor Create(AElement: TDOMElement);
- property Element: TDOMElement read FElement;
- end;
- TDocProject = class;
- { This class represents table of contents with items stored in tree.
- Use your projects toc xml file as input to constructor.}
- TContentItem = class(TXMLItem)
- private
- FChildren: TList;
- FURL: string;
- FName: string;
- FProject: TDocProject;
- function GetChild(Index: Integer): TContentItem;
- function GetChildCount: LongInt;
- procedure ParseElement; override;
- public
- constructor Create(AElement: TDOMElement; AProject: TDocProject);
- destructor Destroy; override;
- property Child[Index: LongInt]: TContentItem read GetChild; default;
- property ChildCount: LongInt read GetChildCount;
- property URL: string read FURL;
- property Name: string read FName;
- end;
- { This class represents whole VampyreDoc project loaded from
- .vdocproj xml file. It contains table of contents loaded
- from toc xml file.}
- TDocProject = class(TXMLItem)
- private
- FProjectFile: string;
- FTitle: string;
- FContentsFile: string;
- FOutputFile: string;
- FRootFile: string;
- FXslDir: string;
- FRefDir: string;
- FContents: TContentItem;
- FFiles: TStrings;
- procedure ParseElement; override;
- public
- constructor Create(AElement: TDOMElement; const AProjectFile: string);
- destructor Destroy; override;
- property ProjectFile: string read FProjectFile;
- property Title: string read FTitle;
- property ContentsFile: string read FContentsFile;
- property OutputFile: string read FOutputFile;
- property RootFile: string read FRootFile;
- property XslDir: string read FXslDir;
- property RefDir: string read FRefDir;
- property Contents: TContentItem read FContents;
- end;
- { Base class for output documentation producers. They take
- project and output directory and transform xml based VampyreDoc
- files to another formats like HTML or CHM.}
- TDocProducer = class(TObject)
- protected
- FName: string;
- public
- procedure Process(Project: TDocProject; const OutDir: string); virtual; abstract;
- property Name: string read FName;
- end;
- TCustomConverter = function(const S, Context: string): string;
- TLinker = class(TObject)
- private
- FDoc: TXMLDocument;
- FResultPath: string;
- FProject: TDocProject;
- FFileName: string;
- FIntendedOutput: string;
- FExternalRefs: TStringList;
- function ResolveExternalLink(const Link: string; const BasePath: string = ''): string;
- procedure CheckElement(Elem: TDOMElement); virtual; abstract;
- function ConvertLink(const Link, Context: string): string; virtual; abstract;
- public
- constructor Create;
- destructor Destroy; override;
- function CheckDocument(const FileName: string; Project: TDocProject): Boolean; virtual;
- procedure SaveResult(const FileName: string);
- procedure DeleteResult;
- property Doc: TXMLDocument read FDoc;
- property References: TStringList read FExternalRefs;
- property IntendedOutput: string read FIntendedOutput write FIntendedOutput;
- end;
- { This class is used by doc producers to convert all links to external
- files in VampyreDoc xml files to format compatible with producer's
- output format.}
- TLinkChecker = class(TLinker)
- private
- FStripDir: Boolean;
- FExtension: string;
- FNewPathDelim: string;
- FDestDir: string;
- FCustomConverter: TCustomConverter;
- FRefFiles: TStringList;
- procedure CheckElement(Elem: TDOMElement); override;
- function ConvertLink(const Link, Context: string): string; override;
- procedure ResolveReferenceLink(Elem: TDOMElement);
- public
- function CheckDocument(const FileName: string; Project: TDocProject): Boolean; override;
- property StripDir: Boolean read FStripDir write FStripDir;
- property Extension: string read FExtension write FExtension;
- property NewPathDelim: string read FNewPathDelim write FNewPathDelim;
- property DestDir: string read FDestDir write FDestDir;
- property CustomConverter: TCustomConverter read FCustomConverter write
- FCustomConverter;
- end;
- { This class checks XSL stylesheet used to transform documents and
- if there are any links (href and src) to existing files these
- files are copied to IntendedOutput's directory.
- If link refers to CSS stylesheet, this sheet is parsed and
- all references to external files (like background-image: url())
- are processed - files are copied to output dir and urls are updated
- (Note: your original CSS styles are not changed! Only styles
- copied to output dir are parsed).)}
- TXSLLinker = class(TLinker)
- private
- procedure CheckElement(Elem: TDOMElement); override;
- function ConvertLink(const Link, Context: string): string; override;
- procedure ParseCSSFile(const DestCSS, SourceCSS: string);
- public
- end;
- { Runs given command line and waits until process ends.
- Returns True if process was successfuly executed.}
- function RunCmdLine(const CmdLine: string): Boolean;
- { Transforms InDoc XML document to OutDoc using StyleSheet XSL file.
- You must have Instant Saxon installed and in OS's search path
- in order to work in Windows.}
- procedure TransformDoc(const InDoc, OutDoc, StyleSheet: string);
- { Returns list filled with filenames of all files contained in project.}
- procedure ProjectToStrings(Project: TDocProject; List: TStrings);
- { Creates files refered by project's toc file but which do not exist yet.}
- procedure GenerateTOCTemplates(Project: TDocProject);
- { Outputs message. Uses Write if compiled as console app or nothing if else.}
- procedure Msg(const S: string);
- implementation
- {$IFDEF MSWINDOWS}
- uses
- Windows;
- {$ENDIF}
- function RunCmdLine(const CmdLine: string): Boolean;
- {$IFDEF MSWINDOWS}
- var
- StartupInfo: TStartupInfo;
- ProcessInfo: TProcessInformation;
- begin
- Result := False;
- FillChar(StartupInfo, SizeOf(StartupInfo), 0);
- with StartupInfo do
- begin
- cb := SizeOf(StartupInfo);
- dwFlags := STARTF_USESHOWWINDOW;
- wShowWindow := SW_SHOW;
- end;
- if CreateProcess(nil, PChar(CmdLine), nil, nil,
- False, NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then
- begin
- repeat
- until WaitForSingleObject(ProcessInfo.hProcess, 1) = WAIT_OBJECT_0;
- CloseHandle(ProcessInfo.hProcess);
- CloseHandle(ProcessInfo.hThread);
- Result := True;
- end
- else
- Msg('Cannot run command line: ' + CmdLine);
- end;
- {$ELSE}
- begin
- Msg('RunCmdLine is not implemented for this platform yet.');
- end;
- {$ENDIF}
- procedure TransformDoc(const InDoc, OutDoc, StyleSheet: string);
- var
- CmdLine: string;
- begin
- CmdLine := Format('saxon-transform -novw -s "%s" -o "%s" "%s"', [InDoc, OutDoc, StyleSheet]);
- if not RunCmdLine(CmdLine) then
- raise Exception.Create('SAXON cannot be executed.');
- end;
- procedure ProjectToStrings(Project: TDocProject; List: TStrings);
- procedure AddItem(Item: TContentItem);
- var
- I: LongInt;
- begin
- List.Add(Item.URL);
- for I := 0 to Item.ChildCount - 1 do
- AddItem(Item[I]);
- end;
- begin
- List.Clear;
- AddItem(Project.FContents);
- List.Add(Project.FContentsFile);
- end;
- procedure GenerateTOCTemplates(Project: TDocProject);
- var
- I: LongInt;
- Stream: TFileStream;
- S, XslPath: string;
- begin
- for I := 0 to Project.FFiles.Count - 1 do
- if not FileExists(Project.FFiles[I]) then
- try
- ForceDirectories(ExtractFileDir(Project.FFiles[I]));
- Stream := TFileStream.Create(Project.FFiles[I], fmCreate);
- XslPath := SwapPathDelims(
- ExtractRelativePath(Project.FFiles[I], Project.FXslDir), sURLDelim);
- S := Format(sXTemplate, [XslPath]);
- Stream.Write(S[1], Length(S));
- Stream.Free;
- except
- end;
- end;
- procedure Msg(const S: string);
- begin
- if System.IsConsole then
- WriteLn(S);
- end;
- { TXMLItem }
- constructor TXMLItem.Create(AElement: TDOMElement);
- begin
- inherited Create;
- FElement := AElement;
- ParseElement;
- end;
- function TXMLItem.FindElement(const NodeName: string; Parent: TDOMElement;
- var Elem: TDOMElement): Boolean;
- var
- I: LongInt;
- begin
- Elem := TDOMElement(Parent.FindNode(NodeName));
- Result := Elem <> nil;
- if (not Result) and (Parent.ChildNodes.Count > 0) then
- for I := 0 to Parent.ChildNodes.Count - 1 do
- begin
- Result := FindElement(NodeName, TDOMElement(Parent.ChildNodes.Item[I]), Elem);
- if Result then
- Break;
- end;
- end;
- { TContentItem }
- constructor TContentItem.Create(AElement: TDOMElement; AProject: TDocProject);
- begin
- FProject := AProject;
- inherited Create(AElement);
- end;
- destructor TContentItem.Destroy;
- var
- I: LongInt;
- begin
- for I := 0 to FChildren.Count - 1 do
- TContentItem(FChildren[I]).Free;
- FChildren.Free;
- inherited Destroy;
- end;
- function TContentItem.GetChild(Index: LongInt): TContentItem;
- begin
- Result := TContentItem(FChildren[Index]);
- end;
- function TContentItem.GetChildCount: LongInt;
- begin
- Result := FChildren.Count;
- end;
- procedure TContentItem.ParseElement;
- var
- I: LongInt;
- Elem: TDOMElement;
- begin
- FChildren := TList.Create;
- // if given element is root of toc file we find first valid
- // toc item element
- if SameText(FElement.NodeName, sXTOCRoot) then
- if not FindElement(sXTOCItem, FElement, Elem) then
- Exit
- else
- FElement := Elem;
- // we assign attributes of toc item element to properties
- FName := FElement.GetAttribute(sXName);
- FURL := SwapPathDelims(FElement.GetAttribute(sXURL));
- FURL := ExpandFileTo(FURL, ExtractFileDir(FProject.ProjectFile));
- if not FileExists(FURL) then
- WriteLn('Warning: TOC item "' + ExtractFileName(FURL) + '" not found.');
- // if toc item contains toc itemlist and this list has some items
- // we add these items to child list of this content item
- if (FElement.FirstChild <> nil) and
- (FElement.FirstChild.ChildNodes.Count > 0) and
- (FElement.NodeType = ELEMENT_NODE) then
- for I := 0 to FElement.FirstChild.GetChildNodes.Count - 1 do
- if Element.FirstChild.ChildNodes.Item[I].NodeType = ELEMENT_NODE then
- begin
- FChildren.Add(TContentItem.Create(
- TDOMElement(FElement.FirstChild.ChildNodes.Item[I]), FProject));
- end;
- end;
- { TDocProject }
- constructor TDocProject.Create(AElement: TDOMElement; const AProjectFile: string);
- begin
- FProjectFile := AProjectFile;
- inherited Create(AElement);
- end;
- destructor TDocProject.Destroy;
- begin
- FFiles.Free;
- FContents.Free;
- inherited Destroy;
- end;
- procedure TDocProject.ParseElement;
- var
- ContDoc: TXMLDocument;
- begin
- FTitle := FElement.FindNode(sXTitle).FirstChild.NodeValue;
- FContentsFile := SwapPathDelims(FElement.FindNode(sXTOCFile).FirstChild.NodeValue);
- FOutputFile := SwapPathDelims(FElement.FindNode(sXOutputFile).FirstChild.NodeValue);
- FRootFile := SwapPathDelims(FElement.FindNode(sXRootFile).FirstChild.NodeValue);
- FXslDir := SwapPathDelims(FElement.FindNode(sXXslDir).FirstChild.NodeValue);
- FRefDir := SwapPathDelims(FElement.FindNode(sXRefDir).FirstChild.NodeValue);
- FContentsFile := ExpandFileTo(FContentsFile, ExtractFileDir(FProjectFile));
- FXslDir := ExpandFileTo(FXslDir, ExtractFileDir(FProjectFile));
- FRefDir := ExpandFileTo(FRefDir, ExtractFileDir(FProjectFile));
- XMLRead.ReadXMLFile(ContDoc, FContentsFile);
- FContents := TContentItem.Create(ContDoc.DocumentElement, Self);
- ContDoc.Free;
- FFiles := TStringList.Create;
- ProjectToStrings(Self, FFiles);
- end;
- { TLinker }
- constructor TLinker.Create;
- begin
- inherited Create;
- FExternalRefs := TStringList.Create;
- FExternalRefs.Sorted := True;
- end;
- destructor TLinker.Destroy;
- begin
- FExternalRefs.Free;
- FDoc.Free;
- inherited Destroy;
- end;
- function TLinker.CheckDocument(const FileName: string;
- Project: TDocProject): Boolean;
- begin
- Result := False;
- FreeAndNil(FDoc);
- FProject := Project;
- FFileName := FileName;
- FExternalRefs.Clear;
- if FileExists(FFileName) then
- try
- XMLRead.ReadXMLFile(FDoc, FFileName);
- FDoc.Encoding := 'utf-8';
- CheckElement(FDoc.DocumentElement);
- Result := True;
- except
- end;
- end;
- procedure TLinker.SaveResult(const FileName: string);
- begin
- if fDoc <> nil then
- begin
- FResultPath := FileName;
- XMLWrite.WriteXMLFile(FDoc, FResultPath);
- end;
- end;
- procedure TLinker.DeleteResult;
- begin
- FreeAndNil(FDoc);
- SysUtils.DeleteFile(FResultPath);
- end;
- function TLinker.ResolveExternalLink(const Link: string; const BasePath: string): string;
- var
- FullPath, Base: string;
- begin
- Base := BasePath;
- if Base = '' then
- Base := FFileName;
- Result := Link;
- FullPath := SwapPathDelims(Result);
- FullPath := ExpandFileTo(FullPath, ExtractFileDir(Base));
- // if this link targets existing external file we copy this
- // file to directory where intended transformed doc will be output
- // and change link's target to only file name with no dir
- if FileExists(FullPath) then
- begin
- CopyFile(PChar(FullPath), PChar(ExtractFileDir(FIntendedOutput) +
- PathDelim + ExtractFileName(FullPath)), False);
- Result := ExtractFileName(FullPath);
- FExternalRefs.Add(Result);
- end;
- end;
- { TLinkChecker }
- function TLinkChecker.CheckDocument(const FileName: string;
- Project: TDocProject): Boolean;
- begin
- FRefFiles := TStringList.Create;
- BuildFileList(Project.FRefDir + PathDelim + '*', faAnyFile, FRefFiles, [flFullNames, flRecursive]);
- Result := inherited CheckDocument(FileName, Project);
- FRefFiles.Free;
- end;
- procedure TLinkChecker.ResolveReferenceLink(Elem: TDOMElement);
- var
- I: LongInt;
- Name, Ref, Link: string;
- Resolved: Boolean;
- begin
- Resolved := False;
- Ref := LowerCase(Elem.FirstChild.NodeValue);
- if Pos('.pas', Ref) > 1 then
- Ref := StringReplace(Ref, '.pas', '_pas', [rfIgnoreCase]);
- for I := 0 to FRefFiles.Count - 1 do
- begin
- Name := LowerCase(ExtractFileName(FRefFiles[I]));
- if Pos(Ref, Name) = 1 then
- begin
- Link := ExtractRelativePath(FIntendedOutput, FRefFiles[I]);
- Link := SwapPathDelims(Link, FNewPathDelim);
- Elem.SetAttribute(sXURL, Link);
- Resolved := True;
- Break;
- end;
- end;
- if not Resolved then
- WriteLn('Warning: Reference to "' + ExtractFileName(FFileName) + '->' +
- Elem.FirstChild.NodeValue + '" not resolved.');
- end;
- procedure TLinkChecker.CheckElement(Elem: TDOMElement);
- var
- I: LongInt;
- Link: string;
- procedure ConvertAttrib(const Name: string);
- var
- Anchor: string;
- begin
- Link := Elem.GetAttribute(Name);
- if Link <> '' then
- begin
- // we must handle links to anchors
- I := Pos(sXAnchorDelim, Link);
- if I > 0 then
- begin
- Anchor := Copy(Link, I, MaxInt);
- Delete(Link, I, MaxInt);
- end;
- Link := ConvertLink(Link, Name);
- if I > 0 then
- Link := Link + Anchor;
- Elem.SetAttribute(Name, Link);
- end;
- end;
- begin
- if Elem.NodeType = ELEMENT_NODE then
- begin
- // convert links in url, anchor and ref attributes of
- // tags like link, listlink, ...
- ConvertAttrib(sXLinkTargetURL);
- ConvertAttrib(sXLinkTargetAnchor);
- // this is only for mail project file and
- // converts root and contents file names (needed by xsl stylesheet
- // when transforming project file)
- if (SameText(Elem.NodeName, sXTOCFile) or
- SameText(Elem.NodeName, sXRef) or
- SameText(Elem.NodeName, sXRootFile)) and
- ((Elem.FirstChild <> nil) and (Elem.FirstChild.NodeValue <> '')) then
- begin
- Link := Elem.FirstChild.NodeValue;
- if not SameText(Elem.NodeName, sXRef) then
- Elem.FirstChild.NodeValue := ConvertLink(Link, Elem.NodeName)
- else
- ResolveReferenceLink(Elem);
- end;
- end;
- for I := 0 to Elem.ChildNodes.Count - 1 do
- CheckElement(TDOMElement(Elem.ChildNodes.Item[I]));
- end;
- function TLinkChecker.ConvertLink(const Link, Context: string): string;
- function FileIsInTOC(const Link: string): Boolean;
- var
- I: LongInt;
- S: string;
- begin
- Result := False;
- S := ExtractFileName(SwapPathDelims(Link));
- for I := 0 to FProject.FFiles.Count - 1 do
- if SameText(ExtractFileName(FProject.FFiles[I]), S) then
- begin
- Result := True;
- Break;
- end;
- end;
- begin
- Result := Link;
- if Result <> '' then
- begin
- if FileIsInTOC(Result) then
- begin
- // for all files in toc (original XML documents)
- // we can strip original directory, add new directory,
- // change file extension and swap path delimiters
- Result := SwapPathDelims(Result);
- if FStripDir then
- Result := ExtractFileName(Result);
- if FDestDir <> '' then
- Result := FDestDir + FNewPathDelim + Result;
- Result := ChangeFileExt(Result, '.' + FExtension);
- Result := SwapPathDelims(Result, FNewPathDelim);
- end
- else
- Result := ResolveExternalLink(Result);
- end;
- if Assigned(FCustomConverter) then
- Result := FCustomConverter(Result, Context);
- end;
- { TXSLLinker }
- procedure TXSLLinker.CheckElement(Elem: TDOMElement);
- var
- I: LongInt;
- Link: string;
- procedure ConvertAttrib(const Name: string);
- begin
- Link := Elem.GetAttribute(Name);
- if Link <> '' then
- begin
- Link := ConvertLink(Link, Name);
- Elem.SetAttribute(Name, Link);
- end;
- end;
- begin
- if Elem.NodeType = ELEMENT_NODE then
- begin
- ConvertAttrib(sXSLHref);
- ConvertAttrib(sXSLSrc);
- end;
- for I := 0 to Elem.ChildNodes.Count - 1 do
- CheckElement(TDOMElement(Elem.ChildNodes.Item[I]));
- end;
- function TXSLLinker.ConvertLink(const Link, Context: string): string;
- begin
- Result := ResolveExternalLink(Link);
- if SameText(GetFileExt(Result), sCSSExt) then
- ParseCSSFile(Result, Link);
- end;
- procedure TXSLLinker.ParseCSSFile(const DestCSS, SourceCSS: string);
- var
- FullPath, FullSourcePath, TheCSS, WriteCSS, Path: string;
- Stream: TFileStream;
- PStart, PEnd, P: PChar;
- Len: LongInt;
- I: LongInt;
- begin
- // first we get path to the destination CSS file which was copied
- // do IntendedOutput's dir by previously called ResolveExternalLink
- FullPath := SwapPathDelims(DestCSS);
- FullPath := ExtractFileDir(FIntendedOutput) + PathDelim +
- ExtractFileName(FullPath);
- // now we get path to the source CSS file
- FullSourcePath := SwapPathDelims(SourceCSS);
- FullSourcePath := ExpandFileTo(FullSourcePath, ExtractFileDir(FFileName));
- // if both files exist we process them
- if FileExists(FullPath) and FileExists(FullSourcePath) then
- begin
- // we read CSS file to memory string
- Stream := TFileStream.Create(FullPath, fmOpenRead);
- SetString(TheCSS, nil, Stream.Size);
- Stream.Read(TheCSS[1], Length(TheCSS));
- Stream.Free;
- WriteCSS := TheCSS;
- // now we are looking for references to external files in CSS
- // (some-property: url(someurl);)
- PStart := StrPos(PChar(TheCSS), sCSSLink);
- while PStart <> nil do
- begin
- PStart := StrPos(PStart, sCSSLinkBStart);
- PEnd := StrPos(PStart, sCSSLinkBEnd);
- if PEnd = nil then
- Break;
- Inc(PStart, Length(sCSSLinkBStart));
- Len := LongInt(PEnd) - LongInt(PStart);
- GetMem(P, Len + 1);
- StrLCopy(P, PStart, Len);
- Path := StrPas(P);
- for I := 1 to Length(Path) do
- if (Path[I] = '''') or (Path[I] = '"') then
- Path[I] := ' ';
- Path := Trim(Path);
- // now we have parameter of CSS's url() function in Path
- // we must resolve this external link but we must
- // use path to the source CSS in resolving (we are handling
- // paths relative to source CSS)
- Path := ResolveExternalLink(Path, FullSourcePath);
- // replace old path with new path in dest CSS
- WriteCSS := StringReplace(WriteCSS, StrPas(P), Path, [rfReplaceAll]);
- FreeMem(P);
- PStart := StrPos(PEnd, sCSSLink);
- end;
- // write dest CSS to the file
- Stream := TFileStream.Create(FullPath, fmCreate);
- Stream.Write(WriteCSS[1], Length(WriteCSS));
- Stream.Free;
- end;
- end;
- end.
|