tools/qdoc3/htmlgenerator.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
--- a/tools/qdoc3/htmlgenerator.cpp	Fri Sep 17 08:34:18 2010 +0300
+++ b/tools/qdoc3/htmlgenerator.cpp	Mon Oct 04 01:19:32 2010 +0300
@@ -219,8 +219,7 @@
       inTableHeader(false),
       numTableRows(0),
       threeColumnEnumValueTable(true),
-      offlineDocs(true),
-      creatorDocs(true),
+      application(Online),
       funcLeftParen("\\S(\\()"),
       myTree(0),
       slow(false),
@@ -271,6 +270,12 @@
     postPostHeader = config.getString(HtmlGenerator::format() +
                                       Config::dot +
                                       HTMLGENERATOR_POSTPOSTHEADER);
+    creatorPostHeader = config.getString(HtmlGenerator::format() +
+                                  Config::dot +
+                                  HTMLGENERATOR_CREATORPOSTHEADER);
+    creatorPostPostHeader = config.getString(HtmlGenerator::format() +
+                                      Config::dot +
+                                      HTMLGENERATOR_CREATORPOSTPOSTHEADER);
     footer = config.getString(HtmlGenerator::format() +
                               Config::dot +
                               HTMLGENERATOR_FOOTER);
@@ -282,8 +287,15 @@
                                           HTMLGENERATOR_GENERATEMACREFS);
 
     project = config.getString(CONFIG_PROJECT);
-    offlineDocs = !config.getBool(CONFIG_ONLINE);
-    creatorDocs = false; //!config.getBool(CONFIG_CREATOR);
+
+    QString app = config.getString(CONFIG_APPLICATION);
+    if (app == "online")
+        application = Online;
+    else if (app == "creator")
+        application = Creator;
+    else 
+        application = Creator;
+
     projectDescription = config.getString(CONFIG_DESCRIPTION);
     if (projectDescription.isEmpty() && !project.isEmpty())
         projectDescription = project + " Reference Documentation";
@@ -364,6 +376,7 @@
     funcIndex.clear();
     legaleseTexts.clear();
     serviceClasses.clear();
+    qmlClasses.clear();
     findAllClasses(tree->root());
     findAllFunctions(tree->root());
     findAllLegaleseTexts(tree->root());
@@ -599,6 +612,9 @@
         else if (atom->string() == "classes") {
             generateCompactList(relative, marker, nonCompatClasses, true);
         }
+        else if (atom->string() == "qmlclasses") {
+            generateCompactList(relative, marker, qmlClasses, true);
+        }
         else if (atom->string().contains("classesbymodule")) {
             QString arg = atom->string().trimmed();
             QString moduleName = atom->string().mid(atom->string().indexOf(
@@ -1477,7 +1493,7 @@
     const QmlClassNode* qml_cn = 0;
     if (fake->subType() == Node::QmlClass) {
         qml_cn = static_cast<const QmlClassNode*>(fake);
-        sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
+        sections = marker->qmlSections(qml_cn,CodeMarker::Summary,0);
         generateTableOfContents(fake,marker,&sections);
     }
     else if (fake->name() != QString("index.html"))
@@ -1559,6 +1575,13 @@
         generateQmlInherits(qml_cn, marker);
         generateQmlInheritedBy(qml_cn, marker);
         generateQmlInstantiates(qml_cn, marker);
+
+        QString allQmlMembersLink = generateAllQmlMembersFile(qml_cn, marker);
+        if (!allQmlMembersLink.isEmpty()) {
+            out() << "<li><a href=\"" << allQmlMembersLink << "\">"
+                  << "List of all members, including inherited members</a></li>\n";
+        }
+
         s = sections.begin();
         while (s != sections.end()) {
             out() << "<a name=\"" << registerRef((*s).name.toLower())
@@ -1578,7 +1601,7 @@
         generateExtractionMark(fake, EndMark);
         //out() << "<hr />\n";
 
-        sections = marker->qmlSections(qml_cn,CodeMarker::Detailed);
+        sections = marker->qmlSections(qml_cn,CodeMarker::Detailed,0);
         s = sections.begin();
         while (s != sections.end()) {
             out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
@@ -1615,7 +1638,7 @@
     }
     else {
         generateExtractionMark(fake, DetailedDescriptionMark);
-        out() << "<div class=\"descr\">\n"; // QTBUG-9504
+        out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
     }
 
     generateBody(fake, marker);
@@ -1701,7 +1724,7 @@
             out() << "</li>\n";
         }
         if (!cn->name().isEmpty())
-            out() << "              <li>" << cn->name() << "</li>\n";
+            out() << "              <li>" << protectEnc(cn->name()) << "</li>\n";
     }
     else if (node->type() == Node::Fake) {
         const FakeNode* fn = static_cast<const FakeNode*>(node);
@@ -1709,52 +1732,50 @@
             out() << "              <li><a href=\"modules.html\">Modules</a></li>";
             QString name =  node->name();
             if (!name.isEmpty())
-                out() << "              <li>" << name << "</li>\n";
+                out() << "              <li>" << protectEnc(name) << "</li>\n";
         }
         else if (node->subType() == Node::Group) {
             if (fn->name() == QString("modules"))
                 out() << "              <li>Modules</li>";
             else {
-                out() << "              <li>" << title << "</li>";
+                out() << "              <li>" << protectEnc(title) << "</li>";
             }
         }
         else if (node->subType() == Node::Page) {
             if (fn->name() == QString("qdeclarativeexamples.html")) {
                 out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
-                out() << "              <li>QML Examples & Demos</li>";
+                out() << "              <li>QML Examples &amp; Demos</li>";
             }
             else if (fn->name().startsWith("examples-")) {
                 out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
-                out() << "              <li>" << title << "</li>";
+                out() << "              <li>" << protectEnc(title) << "</li>";
             }
             else if (fn->name() == QString("namespaces.html")) {
                 out() << "              <li>Namespaces</li>";
             }
             else {
-                out() << "              <li>" << title << "</li>";
+                out() << "              <li>" << protectEnc(title) << "</li>";
             }
         }
         else if (node->subType() == Node::QmlClass) {
             out() << "              <li><a href=\"qdeclarativeelements.html\">QML Elements</a></li>";
-            out() << "              <li>" << title << "</li>";
+            out() << "              <li>" << protectEnc(title) << "</li>";
         }
         else if (node->subType() == Node::Example) {
             out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
             QStringList sl = fn->name().split('/');
             if (sl.contains("declarative"))
-                out() << "              <li><a href=\"qdeclarativeexamples.html\">QML Examples & Demos</a></li>";
+                out() << "              <li><a href=\"qdeclarativeexamples.html\">QML Examples &amp; Demos</a></li>";
             else {
-                QString name = "examples-" + sl.at(0) + ".html";
+                QString name = protectEnc("examples-" + sl.at(0) + ".html"); // this generates an empty link
                 QString t = CodeParser::titleFromName(name);
-                out() << "              <li><a href=\"" << name << "\">"
-                      << t << "</a></li>";
             }
-            out() << "              <li>" << title << "</li>";
+            out() << "              <li>" << protectEnc(title) << "</li>";
         }
     }
     else if (node->type() == Node::Namespace) {
         out() << "              <li><a href=\"namespaces.html\">Namespaces</a></li>";
-        out() << "              <li>" << title << "</li>";
+        out() << "              <li>" << protectEnc(title) << "</li>";
     }
 }
 
@@ -1781,64 +1802,133 @@
         else
             shortVersion = "Qt " + shortVersion + ": ";
     }
-	// Generating page title
+
+    // Generating page title
     out() << "  <title>" << shortVersion << protectEnc(title) << "</title>\n";
-	// Adding style sheet
-	out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />";
-	// Adding jquery and functions - providing online tools and search features
-	out() << "  <script src=\"scripts/jquery.js\" type=\"text/javascript\"></script>\n";
-	out() << "  <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
-	// Adding style and js for small windows
-	out() << "  <script src=\"./scripts/superfish.js\" type=\"text/javascript\"></script>\n";
-	out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/superfish.css\" />";
-	out() << "  <script src=\"./scripts/narrow.js\" type=\"text/javascript\"></script>\n";
-	out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/narrow.css\" />";
+    // Adding style sheet
+    out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />\n";
+    // Adding jquery and functions - providing online tools and search features
+    out() << "  <script src=\"scripts/jquery.js\" type=\"text/javascript\"></script>\n";
+    out() << "  <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
+
 	
-	// Adding syntax highlighter 	// future release
+    // Adding syntax highlighter 	// future release
 	
-	// Setting assistant configuration
-    if (offlineDocs)
-	{
-		out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />"; // Only for Qt Creator
-		out() << "</head>\n";
-		out() << "<body class=\"offline \">\n"; // offline for  Assistant
-	}	
-    if (creatorDocs)
-	{
-		out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />"; // Only for Qt Creator
-		out() << "</head>\n";
-		out() << "<body class=\"offline narrow creator\">\n"; // offline for Creator
-	}	
-	// Setting online doc configuration
-    else
-		{
-		// Browser spec styles
-		out() << "  <!--[if IE]>\n";
-		out() << "<meta name=\"MSSmartTagsPreventParsing\" content=\"true\">\n";
-		out() << "<meta http-equiv=\"imagetoolbar\" content=\"no\">\n";
-		out() << "<![endif]-->\n";
-		out() << "<!--[if lt IE 7]>\n";
-		out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie6.css\">\n";
-		out() << "<![endif]-->\n";
-		out() << "<!--[if IE 7]>\n";
-		out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie7.css\">\n";
-		out() << "<![endif]-->\n";
-		out() << "<!--[if IE 8]>\n";
-		out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie8.css\">\n";
-		out() << "<![endif]-->\n";
+    // Setting some additional style sheet related details depending on configuration (e.g. Online/Creator)
+
+    switch (application) {
+    case Online:
+    // Adding style and js for small windows
+    out() << "  <script src=\"./scripts/superfish.js\" type=\"text/javascript\"></script>\n";
+    out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/superfish.css\" />";
+    out() << "  <script src=\"./scripts/narrow.js\" type=\"text/javascript\"></script>\n";
+    out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/narrow.css\" />\n";	
+        // Browser spec styles
+	out() << "  <!--[if IE]>\n";
+	out() << "<meta name=\"MSSmartTagsPreventParsing\" content=\"true\">\n";
+	out() << "<meta http-equiv=\"imagetoolbar\" content=\"no\">\n";
+	out() << "<![endif]-->\n";
+	out() << "<!--[if lt IE 7]>\n";
+	out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie6.css\">\n";
+	out() << "<![endif]-->\n";
+	out() << "<!--[if IE 7]>\n";
+	out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie7.css\">\n";
+	out() << "<![endif]-->\n";
+	out() << "<!--[if IE 8]>\n";
+	out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie8.css\">\n";
+	out() << "<![endif]-->\n";
 		
-		out() << "</head>\n";
-		// CheckEmptyAndLoadList activating search
-		out() << "<body class=\"\" onload=\"CheckEmptyAndLoadList();\">\n";
-		}
+	out() << "</head>\n";
+	// CheckEmptyAndLoadList activating search
+	out() << "<body class=\"\" onload=\"CheckEmptyAndLoadList();\">\n";
+        break;
+    case Creator:
+	out() << "</head>\n";
+	out() << "<body class=\"offline narrow creator\">\n"; // offline narrow
+        break;
+    default:
+	out() << "</head>\n";
+	out() << "<body>\n";
+        break;
+    }
 
 #ifdef GENERATE_MAC_REFS    
     if (mainPage)
         generateMacRef(node, marker);
-#endif    
-    out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version());
-    generateBreadCrumbs(title,node,marker);
-    out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
+#endif   
+ 
+    switch (application) {
+    case Online:
+        out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version());
+        generateBreadCrumbs(title,node,marker);
+        out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
+        break;
+    case Creator:
+        out() << QString(creatorPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
+        generateBreadCrumbs(title,node,marker);
+        out() << QString(creatorPostPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());	
+        break;
+    default: // default -- not used except if one forgets to set any of the above settings to true
+        out() << QString(creatorPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
+        generateBreadCrumbs(title,node,marker);
+        out() << QString(creatorPostPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
+        break;
+    }
+
+        navigationLinks.clear();
+
+    if (node && !node->links().empty()) {
+        QPair<QString,QString> linkPair;
+        QPair<QString,QString> anchorPair;
+        const Node *linkNode;
+
+        if (node->links().contains(Node::PreviousLink)) {
+            linkPair = node->links()[Node::PreviousLink];
+            linkNode = findNodeForTarget(linkPair.first, node, marker);
+            if (!linkNode || linkNode == node)
+                anchorPair = linkPair;
+            else
+                anchorPair = anchorForNode(linkNode);
+
+            out() << "  <link rel=\"prev\" href=\""
+                  << anchorPair.first << "\" />\n";
+
+            navigationLinks += "[Previous: <a href=\"" + anchorPair.first + "\">";
+            if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
+                navigationLinks += protect(anchorPair.second);
+            else
+                navigationLinks += protect(linkPair.second);
+            navigationLinks += "</a>]\n";
+        }
+        if (node->links().contains(Node::NextLink)) {
+            linkPair = node->links()[Node::NextLink];
+            linkNode = findNodeForTarget(linkPair.first, node, marker);
+            if (!linkNode || linkNode == node)
+                anchorPair = linkPair;
+            else
+                anchorPair = anchorForNode(linkNode);
+
+            out() << "  <link rel=\"next\" href=\""
+                  << anchorPair.first << "\" />\n";
+
+            navigationLinks += "[Next: <a href=\"" + anchorPair.first + "\">";
+            if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
+                navigationLinks += protect(anchorPair.second);
+            else
+                navigationLinks += protect(linkPair.second);
+            navigationLinks += "</a>]\n";
+        }
+        if (node->links().contains(Node::StartLink)) {
+            linkPair = node->links()[Node::StartLink];
+            linkNode = findNodeForTarget(linkPair.first, node, marker);
+            if (!linkNode || linkNode == node)
+                anchorPair = linkPair;
+            else
+                anchorPair = anchorForNode(linkNode);
+            out() << "  <link rel=\"start\" href=\""
+                  << anchorPair.first << "\" />\n";
+        }
+    }
 
 #if 0 // Removed for new doc format. MWS
     if (node && !node->links().empty())
@@ -1872,30 +1962,30 @@
 
     out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version())
           << QString(address).replace("\\" + COMMAND_VERSION, myTree->version());
-	
-	    if (offlineDocs)
-		{
-          out() << "</body>\n";
-		}
-	    if (creatorDocs)
-		{
-          out() << "</body>\n";
-		}
-		else
-		{
-			out() << "  <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
-			out() << "  <!-- <script type=\"text/javascript\">\n";
-			out() << "  var _gaq = _gaq || [];\n";
-			out() << "  _gaq.push(['_setAccount', 'UA-4457116-5']);\n";
-			out() << "  _gaq.push(['_trackPageview']);\n";
-			out() << "  (function() {\n";
-			out() << "  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n";
-			out() << "  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n";
-			out() << "  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n";
-			out() << "  })();\n";
-			out() << "  </script> -->\n";
-			out() << "</body>\n";
-		}
+
+    switch (application) {
+    case Online:
+        out() << "  <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
+        out() << "  <!-- <script type=\"text/javascript\">\n";
+        out() << "  var _gaq = _gaq || [];\n";
+        out() << "  _gaq.push(['_setAccount', 'UA-4457116-5']);\n";
+        out() << "  _gaq.push(['_trackPageview']);\n";
+        out() << "  (function() {\n";
+        out() << "  var ga = document.createElement('script'); ";
+        out() << "ga.type = 'text/javascript'; ga.async = true;\n";
+        out() << "  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + ";
+        out() << "'.google-analytics.com/ga.js';\n";
+        out() << "  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n";
+        out() << "  })();\n";
+        out() << "  </script> -->\n";
+        out() << "</body>\n";
+	break;
+    case Creator:
+        out() << "</body>\n";
+	break;
+    default:
+        out() << "</body>\n";
+    }
           out() <<   "</html>\n";
 }
 
@@ -1907,11 +1997,14 @@
         generateExtractionMark(node, BriefMark);
         out() << "<p>";
         generateText(brief, node, marker);
+
         if (!relative || node == relative)
             out() << " <a href=\"#";
         else
             out() << " <a href=\"" << linkForNode(node, relative) << "#";
         out() << registerRef("details") << "\">More...</a></p>\n";
+
+
         generateExtractionMark(node, EndMark);
     }
 }
@@ -1928,7 +2021,7 @@
 }
 
 /*!
-  Generates a table of contents begining at \a node.
+  Generates a table of contents beginning at \a node.
  */
 void HtmlGenerator::generateTableOfContents(const Node *node,
                                             CodeMarker *marker,
@@ -2014,7 +2107,7 @@
 
 /*!
   Revised for the new doc format.
-  Generates a table of contents begining at \a node.
+  Generates a table of contents beginning at \a node.
  */
 void HtmlGenerator::generateTableOfContents(const Node *node,
                                             CodeMarker *marker,
@@ -2192,6 +2285,38 @@
     return fileName;
 }
 
+/*!
+  This function creates an html page on which are listed all
+  the members of QML class \a qml_cn, including the inherited
+  members. The \a marker is used for formatting stuff.
+ */
+QString HtmlGenerator::generateAllQmlMembersFile(const QmlClassNode* qml_cn,
+                                                 CodeMarker* marker)
+{
+    QList<Section> sections;
+    QList<Section>::ConstIterator s;
+
+    sections = marker->qmlSections(qml_cn,CodeMarker::SeparateList,myTree);
+    if (sections.isEmpty())
+        return QString();
+
+    QString fileName = fileBase(qml_cn) + "-members." + fileExtension(qml_cn);
+    beginSubPage(qml_cn->location(), fileName);
+    QString title = "List of All Members for " + qml_cn->name();
+    generateHeader(title, qml_cn, marker);
+    generateTitle(title, Text(), SmallSubTitle, qml_cn, marker);
+    out() << "<p>This is the complete list of members for ";
+    generateFullName(qml_cn, 0, marker);
+    out() << ", including inherited members.</p>\n";
+
+    Section section = sections.first();
+    generateSectionList(section, 0, marker, CodeMarker::SeparateList);
+
+    generateFooter();
+    endSubPage();
+    return fileName;
+}
+
 QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner,
                                                    CodeMarker *marker,
                                                    CodeMarker::Status status)
@@ -3052,7 +3177,14 @@
             if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
                 par1 = QStringRef();
                 const Node* n = marker->resolveTarget(arg.toString(), myTree, relative, self);
-                addLink(linkForNode(n,relative), arg, &html);
+                if (n && n->subType() == Node::QmlBasicType) {
+                    if (relative && relative->subType() == Node::QmlClass)
+                        addLink(linkForNode(n,relative), arg, &html);
+                    else 
+                        html += arg.toString();
+                }
+                else
+                    addLink(linkForNode(n,relative), arg, &html);
                 handled = true;
             }
             else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
@@ -3414,7 +3546,7 @@
         return QString();
     if (node->access() == Node::Private)
         return QString();
-
+ 
     fn = fileName(node);
 /*    if (!node->url().isEmpty())
         return fn;*/
@@ -3587,6 +3719,12 @@
                 if (!serviceName.isEmpty())
                     serviceClasses.insert(serviceName, *c);
             }
+            else if ((*c)->type() == Node::Fake &&
+                     (*c)->subType() == Node::QmlClass &&
+                     !(*c)->doc().isEmpty()) {
+                QString qmlClassName = (*c)->name();
+                qmlClasses.insert(qmlClassName,*c);
+            }
             else if ((*c)->isInnerNode()) {
                 findAllClasses(static_cast<InnerNode *>(*c));
             }
@@ -4292,57 +4430,103 @@
         return true;
     if (node->access() == Node::Private)
         return false;
-    if (!node->isInnerNode())
-        return false;
-
+
+    QString guid = QUuid::createUuid().toString();
+    QString url = PageGenerator::fileName(node);
     QString title;
     QString rawTitle;
     QString fullTitle;
-    const InnerNode* inner = static_cast<const InnerNode*>(node);
-        
-    writer.writeStartElement("page");
+    QStringList pageWords;
     QXmlStreamAttributes attributes;
-    QString t;
-    t.setNum(id++);
-    switch (node->type()) {
-    case Node::Fake:
-        {
-            const FakeNode* fake = static_cast<const FakeNode*>(node);
-            title = fake->fullTitle();
-            break;
-        }
-    case Node::Class:
-        {
-            title = node->name() + " Class Reference";
+
+    writer.writeStartElement("page");
+
+    if (node->isInnerNode()) {
+        const InnerNode* inner = static_cast<const InnerNode*>(node);
+        if (!inner->pageKeywords().isEmpty())
+            pageWords << inner->pageKeywords();
+
+        switch (node->type()) {
+        case Node::Fake:
+            {
+                const FakeNode* fake = static_cast<const FakeNode*>(node);
+                title = fake->fullTitle();
+                pageWords << title;
+                break;
+            }
+        case Node::Class:
+            {
+                title = node->name() + " Class Reference";
+                pageWords << node->name() << "class" << "reference";
+                break;
+            }
+        case Node::Namespace:
+            {
+                rawTitle = marker->plainName(inner);
+                fullTitle = marker->plainFullName(inner);
+                title = rawTitle + " Namespace Reference";
+                pageWords << rawTitle << "namespace" << "reference";
+                break;
+            }
+        default:
+            title = node->name();
+            pageWords << title;
             break;
         }
-    case Node::Namespace:
-        {
-            rawTitle = marker->plainName(inner);
-            fullTitle = marker->plainFullName(inner);
-            title = rawTitle + " Namespace Reference";
+    }
+    else {
+        switch (node->type()) {
+        case Node::Enum:
+            {
+                title = node->name() + " Enum Reference";
+                pageWords << node->name() << "enum" << "type";
+                url += "#" + node->name() + "-enum";
+                break;
+            }
+        case Node::Function:
+            {
+                title = node->name() + " Function Reference";
+                pageWords << node->name() << "function";
+                url += "#" + node->name();
+                break;
+            }
+        case Node::Property:
+            {
+                title = node->name() + " Property Reference";
+                pageWords << node->name() << "property";
+                url += "#" + node->name() + "-prop";
+                break;
+            }
+        case Node::Typedef:
+            {
+                title = node->name() + " Type Reference";
+                pageWords << node->name() << "typedef" << "type";
+                url += "#" + node->name();
+                break;
+            }
+        default:
+            title = node->name();
+            pageWords << title;
             break;
         }
-    default:
-        title = node->name();
-        break;
-    }
-    writer.writeAttribute("id",t);
-    writer.writeStartElement("pageWords");
-    writer.writeCharacters(title);
-    if (!inner->pageKeywords().isEmpty()) {
-        const QStringList& w = inner->pageKeywords();
-        for (int i = 0; i < w.size(); ++i) {
-            writer.writeCharacters(" ");
-            writer.writeCharacters(w.at(i).toLocal8Bit().constData());
+
+        Node* parent = node->parent();
+        if (parent && ((parent->type() == Node::Class) ||
+                       (parent->type() == Node::Namespace))) {
+            pageWords << parent->name();
         }
     }
+
+    writer.writeAttribute("id",guid);
+    writer.writeStartElement("pageWords");
+    writer.writeCharacters(pageWords.join(" "));
+
     writer.writeEndElement();
     writer.writeStartElement("pageTitle");
     writer.writeCharacters(title);
     writer.writeEndElement();
     writer.writeStartElement("pageUrl");
-    writer.writeCharacters(PageGenerator::fileName(node));
+    writer.writeCharacters(url);
     writer.writeEndElement();
     writer.writeStartElement("pageType");
     switch (node->pageType()) {
@@ -4360,6 +4544,35 @@
     }
     writer.writeEndElement();
     writer.writeEndElement();
+
+    if (node->type() == Node::Fake && node->doc().hasTableOfContents()) {
+        QList<Atom*> toc = node->doc().tableOfContents();
+        if (!toc.isEmpty()) {
+            for (int i = 0; i < toc.size(); ++i) {
+                Text headingText = Text::sectionHeading(toc.at(i));
+                QString s = headingText.toString();
+                writer.writeStartElement("page");
+                guid = QUuid::createUuid().toString();
+                QString internalUrl = url + "#" + Doc::canonicalTitle(s);
+                writer.writeAttribute("id",guid);
+                writer.writeStartElement("pageWords");
+                writer.writeCharacters(pageWords.join(" "));
+                writer.writeCharacters(" ");
+                writer.writeCharacters(s);
+                writer.writeEndElement();
+                writer.writeStartElement("pageTitle");
+                writer.writeCharacters(s);
+                writer.writeEndElement();
+                writer.writeStartElement("pageUrl");
+                writer.writeCharacters(internalUrl);
+                writer.writeEndElement();
+                writer.writeStartElement("pageType");
+                writer.writeCharacters("Article");
+                writer.writeEndElement();
+                writer.writeEndElement();
+            }
+        }
+    }
     return true;
 }