wiki: simple toc

git-svn-id: trunk@35893 -
This commit is contained in:
mattias 2012-03-11 18:28:21 +00:00
parent cc9350c2d2
commit ddffec7238

View File

@ -42,6 +42,9 @@ type
protected protected
BodyDOMNode: TDOMElement; BodyDOMNode: TDOMElement;
CurDOMNode: TDOMElement; // current xhtml node CurDOMNode: TDOMElement; // current xhtml node
TOCNode: TDOMElement;
CurTOCNode: TDOMElement;
TOCNodeCount: integer;
SectionLevel: integer; SectionLevel: integer;
Stack: PW2XHTMLStackItem; Stack: PW2XHTMLStackItem;
StackPtr: integer; StackPtr: integer;
@ -60,12 +63,14 @@ type
TWiki2XHTMLConverter = class(TWiki2FormatConverter) TWiki2XHTMLConverter = class(TWiki2FormatConverter)
private private
FAddLinksToTranslations: boolean; FAddLinksToTranslations: boolean;
FAddTOCIfHeaderCountMoreThan: integer;
FCSSFilename: string; FCSSFilename: string;
FLinkToBaseDocument: string; FLinkToBaseDocument: string;
FMaxH: integer; FMaxH: integer;
FPageFileExt: string; FPageFileExt: string;
procedure DoAddLinksToTranslations(var doc: TXMLDocument; procedure DoAddLinksToTranslations(Page: TW2XHTMLPage);
var Page: TW2XHTMLPage); procedure DoAddLinkToBaseDocument(Page: TW2XHTMLPage);
procedure OnHeaderToken(Token: TWPToken);
procedure SetCSSFilename(AValue: string); procedure SetCSSFilename(AValue: string);
procedure SetMaxH(AValue: integer); procedure SetMaxH(AValue: integer);
procedure SetPageFileExt(AValue: string); procedure SetPageFileExt(AValue: string);
@ -73,6 +78,7 @@ type
ShortFilenameToPage: TFilenameToPointerTree; // created in ConvertInit ShortFilenameToPage: TFilenameToPointerTree; // created in ConvertInit
UsedImages: TFilenameToPointerTree; // image name to first page using the image UsedImages: TFilenameToPointerTree; // image name to first page using the image
procedure OnWikiToken(Token: TWPToken); virtual; procedure OnWikiToken(Token: TWPToken); virtual;
procedure RaiseNodeNotOpen(Token: TWPToken);
function GetImageLink(ImgFilename: string): string; virtual; function GetImageLink(ImgFilename: string): string; virtual;
function FindImage(const ImgFilename: string): string; virtual; function FindImage(const ImgFilename: string): string; virtual;
procedure MarkImageAsUsed(const ImgFilename: string; Page: TW2XHTMLPage); virtual; procedure MarkImageAsUsed(const ImgFilename: string; Page: TW2XHTMLPage); virtual;
@ -97,7 +103,9 @@ type
function PageToFilename(Page: TW2XHTMLPage; Full: boolean): string; virtual; function PageToFilename(Page: TW2XHTMLPage; Full: boolean): string; virtual;
property PageFileExt: string read FPageFileExt write SetPageFileExt; property PageFileExt: string read FPageFileExt write SetPageFileExt;
property LinkToBaseDocument: string read FLinkToBaseDocument write FLinkToBaseDocument; property LinkToBaseDocument: string read FLinkToBaseDocument write FLinkToBaseDocument;
property AddLinksToTranslations: boolean read FAddLinksToTranslations write FAddLinksToTranslations; property AddLinksToTranslations: boolean read FAddLinksToTranslations write FAddLinksToTranslations default true;
property AddTOCIfHeaderCountMoreThan: integer read FAddTOCIfHeaderCountMoreThan
write FAddTOCIfHeaderCountMoreThan default 2;
end; end;
implementation implementation
@ -110,8 +118,7 @@ begin
FCSSFilename:=AValue; FCSSFilename:=AValue;
end; end;
procedure TWiki2XHTMLConverter.DoAddLinksToTranslations(var doc: TXMLDocument; procedure TWiki2XHTMLConverter.DoAddLinksToTranslations(Page: TW2XHTMLPage);
var Page: TW2XHTMLPage);
var var
TranslationPage: TW2XHTMLPage; TranslationPage: TW2XHTMLPage;
Lang: String; Lang: String;
@ -122,7 +129,9 @@ var
LinkNode: TDOMElement; LinkNode: TDOMElement;
Captions: TStringList; Captions: TStringList;
i: Integer; i: Integer;
doc: TXMLDocument;
begin begin
doc:=Page.XHTML;
GetPageTranslations(Page.WikiDocumentName, LangToPage); GetPageTranslations(Page.WikiDocumentName, LangToPage);
//debugln(['TWiki2XHTMLConverter.DoAddLinksToTranslations ',Page.WikiDocumentName,' ',LangToPage.Count]); //debugln(['TWiki2XHTMLConverter.DoAddLinksToTranslations ',Page.WikiDocumentName,' ',LangToPage.Count]);
Captions:=TStringList.Create; Captions:=TStringList.Create;
@ -166,6 +175,85 @@ begin
end; end;
end; end;
procedure TWiki2XHTMLConverter.DoAddLinkToBaseDocument(Page: TW2XHTMLPage);
var
Link: String;
Node: TDOMElement;
doc: TXMLDocument;
begin
// add <a href="BaseURL+WikiDocumentName">LinkToBaseDocument</a><br>
doc:=Page.XHTML;
Node:=doc.CreateElement('a');
Page.BodyDOMNode.AppendChild(Node);
Link:=Page.WikiPage.BaseURL;
if (Link<>'') and (Link[length(Link)]<>'/') then
Link+='/';
Link+=Page.WikiDocumentName;
Node.SetAttribute('href', Link);
Node.AppendChild(doc.CreateTextNode(LinkToBaseDocument));
Node:=doc.CreateElement('br');
Page.BodyDOMNode.AppendChild(Node);
end;
procedure TWiki2XHTMLConverter.OnHeaderToken(Token: TWPToken);
var
LinkNode: TDOMElement;
HeaderTxt: DOMString;
Page: TW2XHTMLPage;
doc: TXMLDocument;
NodeName: String;
NodeClass: String;
Node: TDOMElement;
HRef: String;
LINode: TDOMElement;
begin
Page:=TW2XHTMLPage(Token.UserData);
doc:=Page.XHTML;
NodeClass:='';
if Page.SectionLevel<=1 then
NodeName:='h1'
else if Page.SectionLevel<=MaxH then
NodeName:='h'+IntToStr(Page.SectionLevel)
else if Page.SectionLevel>MaxH then begin
NodeName:='h'+IntToStr(MaxH);
NodeClass:='subTitle';
end;
if Token.Range=wprOpen then begin
// open header
Node:=doc.CreateElement(NodeName);
Page.CurDOMNode.AppendChild(Node);
if NodeClass<>'' then
Node.SetAttribute('class', NodeClass);
Page.CurDOMNode:=Node;
Page.Push(Node, wptHeader);
end else if Token.Range=wprClose then begin
// close header
if Page.CurDOMNode.TagName<>NodeName then
RaiseNodeNotOpen(Token);
HeaderTxt:='';
if Page.CurDOMNode.FirstChild is TDOMText then
HeaderTxt:=TDOMText(Page.CurDOMNode.FirstChild).Data;
if HeaderTxt<>'' then begin
HRef:=WikiHeaderToLink(HeaderTxt);
// add anchor
LinkNode:=doc.CreateElement('a');
LinkNode.SetAttribute('name', HRef);
Page.CurDOMNode.ParentNode.InsertBefore(LinkNode, Page.CurDOMNode);
// add TOC link
LINode:=doc.CreateElement('li');
LINode.SetAttribute('class', 'toclevel-'+IntToStr(Page.SectionLevel));
Page.CurTOCNode.AppendChild(LINode);
LinkNode:=doc.CreateElement('a');
LinkNode.SetAttribute('href', '#'+HRef);
LinkNode.AppendChild(doc.CreateTextNode(HeaderTxt));
LINode.AppendChild(LinkNode);
inc(Page.TOCNodeCount);
end;
Page.CurDOMNode:=Page.CurDOMNode.ParentNode as TDOMElement;
Page.Pop;
end;
end;
procedure TWiki2XHTMLConverter.SetMaxH(AValue: integer); procedure TWiki2XHTMLConverter.SetMaxH(AValue: integer);
begin begin
if AValue<1 then AValue:=1; if AValue<1 then AValue:=1;
@ -339,7 +427,6 @@ var
CSSNode: TDOMElement; CSSNode: TDOMElement;
Node: TDOMElement; Node: TDOMElement;
CurCSSFilename: String; CurCSSFilename: String;
Link: String;
begin begin
Page.ClearConversion; Page.ClearConversion;
if Page.WikiPage=nil then exit; if Page.WikiPage=nil then exit;
@ -380,29 +467,28 @@ begin
// links to translations // links to translations
if AddLinksToTranslations then if AddLinksToTranslations then
DoAddLinksToTranslations(doc,Page); DoAddLinksToTranslations(Page);
try try
Page.SectionLevel:=0; Page.SectionLevel:=0;
Page.TOCNode:=doc.CreateElement('ul');
Page.TOCNodeCount:=0;
Page.CurTOCNode:=Page.TOCNode;
Page.BodyDOMNode.AppendChild(Page.TOCNode);
Page.CurDOMNode:=Page.BodyDOMNode; Page.CurDOMNode:=Page.BodyDOMNode;
Page.WikiPage.Parse(@OnWikiToken,Page); Page.WikiPage.Parse(@OnWikiToken,Page);
if LinkToBaseDocument<>'' then begin if LinkToBaseDocument<>'' then
// add <a href="BaseURL+WikiDocumentName">LinkToBaseDocument</a><br> DoAddLinkToBaseDocument(Page);
Node:=doc.CreateElement('a');
Page.BodyDOMNode.AppendChild(Node); if Page.TOCNodeCount<=AddTOCIfHeaderCountMoreThan then
Link:=Page.WikiPage.BaseURL; Page.TOCNode.Free;
if (Link<>'') and (Link[length(Link)]<>'/') then
Link+='/';
Link+=Page.WikiDocumentName;
Node.SetAttribute('href',Link);
Node.AppendChild(doc.CreateTextNode(LinkToBaseDocument));
Node:=doc.CreateElement('br');
Page.BodyDOMNode.AppendChild(Node);
end;
finally finally
Page.BodyDOMNode:=nil; Page.BodyDOMNode:=nil;
Page.CurDOMNode:=nil; Page.CurDOMNode:=nil;
Page.TOCNode:=nil;
Page.CurTOCNode:=nil;
end; end;
end; end;
@ -411,12 +497,6 @@ var
Page: TW2XHTMLPage; Page: TW2XHTMLPage;
W: TWikiPage; W: TWikiPage;
procedure NodeNotOpen;
begin
raise Exception.Create('TWiki2XHTMLConverter.OnWikiToken can not close:'
+' Token='+dbgs(Token.Token)+' '+DbgSName(Token)+' CurNode='+Page.CurDOMNode.TagName);
end;
procedure MissingNodeName; procedure MissingNodeName;
begin begin
raise Exception.Create('TWiki2XHTMLConverter.OnWikiToken have no node name:' raise Exception.Create('TWiki2XHTMLConverter.OnWikiToken have no node name:'
@ -432,7 +512,6 @@ var
NameValueToken: TWPNameValueToken; NameValueToken: TWPNameValueToken;
CurName: String; CurName: String;
CurValue: String; CurValue: String;
HeaderTxt: DOMString;
begin begin
Page:=TW2XHTMLPage(Token.UserData); Page:=TW2XHTMLPage(Token.UserData);
W:=Page.WikiPage; W:=Page.WikiPage;
@ -466,8 +545,7 @@ begin
wptSup, wptSub, wptSmall, wptEm, wptSpan, wptString, wptVar, wptKey, wptSup, wptSub, wptSmall, wptEm, wptSpan, wptString, wptVar, wptKey,
wptPre, wptCenter, wptPre, wptCenter,
wptBulletList, wptNumberedList, wptDefinitionList, wptBulletList, wptNumberedList, wptDefinitionList,
wptTable, wptTableRow, wptTableCell, wptTableHeadCell, wptTable, wptTableRow, wptTableCell, wptTableHeadCell:
wptSection:
begin begin
// simple range // simple range
NodeClass:=''; NodeClass:='';
@ -500,16 +578,6 @@ begin
wptTableRow: NodeName:='tr'; wptTableRow: NodeName:='tr';
wptTableCell: NodeName:='td'; wptTableCell: NodeName:='td';
wptTableHeadCell: NodeName:='th'; wptTableHeadCell: NodeName:='th';
wptSection:
begin
NodeName:='div';
NodeClass:='section';
if Token.Range=wprOpen then
inc(Page.SectionLevel)
else if Token.Range=wprClose then
dec(Page.SectionLevel);
end;
end; end;
if NodeName='' then if NodeName='' then
MissingNodeName; MissingNodeName;
@ -523,48 +591,49 @@ begin
exit; exit;
end else if Token.Range=wprClose then begin end else if Token.Range=wprClose then begin
if Page.CurDOMNode.TagName<>NodeName then if Page.CurDOMNode.TagName<>NodeName then
NodeNotOpen; RaiseNodeNotOpen(Token);
Page.CurDOMNode:=Page.CurDOMNode.ParentNode as TDOMElement; Page.CurDOMNode:=Page.CurDOMNode.ParentNode as TDOMElement;
exit; exit;
end; end;
end; end;
wptSection:
begin
NodeName:='div';
if Token.Range=wprOpen then begin
inc(Page.SectionLevel);
// start div
Node:=doc.CreateElement(NodeName);
Page.CurDOMNode.AppendChild(Node);
Node.SetAttribute('class','section');
Page.CurDOMNode:=Node;
// start TOC list
Node:=doc.CreateElement('ul');
Page.CurTOCNode.AppendChild(Node);
Page.CurTOCNode:=Node;
Page.Push(Node,Token.Token);
exit;
end else if Token.Range=wprClose then begin
dec(Page.SectionLevel);
// end div
if Page.CurDOMNode.TagName<>NodeName then
RaiseNodeNotOpen(Token);
Page.CurDOMNode:=Page.CurDOMNode.ParentNode as TDOMElement;
// end TOC list
Node:=Page.CurTOCNode;
Page.CurTOCNode:=Node.ParentNode as TDOMElement;
if Node.FirstChild=nil then
Node.Free;
Page.Pop;
exit;
end;
end;
wptHeader: wptHeader:
begin begin
if Page.SectionLevel<=1 then OnHeaderToken(Token);
NodeName:='h1'
else if Page.SectionLevel<=MaxH then
NodeName:='h'+IntToStr(Page.SectionLevel)
else if Page.SectionLevel>MaxH then begin
NodeName:='h'+IntToStr(MaxH);
NodeClass:='subTitle';
end;
if Token.Range=wprOpen then begin
// open header
Node:=doc.CreateElement(NodeName);
Page.CurDOMNode.AppendChild(Node);
if NodeClass<>'' then
Node.SetAttribute('class',NodeClass);
Page.CurDOMNode:=Node;
Page.Push(Node,wptHeader);
exit; exit;
end else if Token.Range=wprClose then begin
// close header
if Page.CurDOMNode.TagName<>NodeName then
NodeNotOpen;
HeaderTxt:='';
if Page.CurDOMNode.FirstChild is TDOMText then
HeaderTxt:=TDOMText(Page.CurDOMNode.FirstChild).Data;
if HeaderTxt<>'' then begin
// add anchor
Node:=doc.CreateElement('a');
Node.SetAttribute('name',WikiHeaderToLink(HeaderTxt));
Page.CurDOMNode.ParentNode.InsertBefore(Node,Page.CurDOMNode);
end;
Page.CurDOMNode:=Page.CurDOMNode.ParentNode as TDOMElement;
Page.Pop;
exit;
end;
end; end;
wptListItem: wptListItem:
@ -580,7 +649,7 @@ begin
end else if Token.Range=wprClose then begin end else if Token.Range=wprClose then begin
if (Page.CurDOMNode.TagName<>'dd') if (Page.CurDOMNode.TagName<>'dd')
and (Page.CurDOMNode.TagName<>'li') then and (Page.CurDOMNode.TagName<>'li') then
NodeNotOpen; RaiseNodeNotOpen(Token);
Page.CurDOMNode:=Page.CurDOMNode.ParentNode as TDOMElement; Page.CurDOMNode:=Page.CurDOMNode.ParentNode as TDOMElement;
exit; exit;
end; end;
@ -631,6 +700,15 @@ begin
Log('TWiki2XHTMLConverter.OnWikiToken ToDo: Token='+dbgs(Token.Token)+' Range='+dbgs(Token.Range)+' Class='+Token.ClassName+' '+W.PosToStr(W.CurrentPos)); Log('TWiki2XHTMLConverter.OnWikiToken ToDo: Token='+dbgs(Token.Token)+' Range='+dbgs(Token.Range)+' Class='+Token.ClassName+' '+W.PosToStr(W.CurrentPos));
end; end;
procedure TWiki2XHTMLConverter.RaiseNodeNotOpen(Token: TWPToken);
var
Page: TW2XHTMLPage;
begin
Page:=TW2XHTMLPage(Token.UserData);
raise Exception.Create('TWiki2XHTMLConverter.OnWikiToken can not close:'
+' Token='+dbgs(Token.Token)+' '+DbgSName(Token)+' CurNode='+Page.CurDOMNode.TagName);
end;
function TWiki2XHTMLConverter.GetImageLink(ImgFilename: string): string; function TWiki2XHTMLConverter.GetImageLink(ImgFilename: string): string;
begin begin
Result:=CreateRelativePath(ImgFilename,OutputDir); Result:=CreateRelativePath(ImgFilename,OutputDir);
@ -853,6 +931,7 @@ begin
UsedImages:=TFilenameToPointerTree.Create(false); UsedImages:=TFilenameToPointerTree.Create(false);
fLinkToBaseDocument:='Online version'; fLinkToBaseDocument:='Online version';
FAddLinksToTranslations:=true; FAddLinksToTranslations:=true;
FAddTOCIfHeaderCountMoreThan:=2;
end; end;
destructor TWiki2XHTMLConverter.Destroy; destructor TWiki2XHTMLConverter.Destroy;