qdoc: Generate \keyword anchors at the top of the page

Currently, qdoc processes \keyword and \target the same way. The
negative effect of this is that when either command appears at the top
of a qdoc comment, the anchor it generates in the html file is just
above the details section on the html page. This is usually wrong,
especially for \keyword commands, where the anchor generated should
always be at the top of the page/text where the \keyword appears. This
update implements that. \target anchors are meant to be used when the
anchor should appear somewhere in the middle of the page/text, exactly
where the \target command appears.

Change-Id: Ibbbf1087562a977ff74ccd98febfe9310ecba8f0
Task-number: QTBUG-42290
Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
This commit is contained in:
Martin Smith 2014-10-30 15:22:17 +01:00
parent 8bed6b6a7f
commit 1936e4973f
6 changed files with 37 additions and 4 deletions

View File

@ -97,6 +97,9 @@ QT_BEGIN_NAMESPACE
\value ImageText \value ImageText
\value ImportantNote \value ImportantNote
\value InlineImage \value InlineImage
\value JavaScript
\value EndJavaScript
\value Keyword
\value LineBreak \value LineBreak
\value Link \value Link
\value LinkNode \value LinkNode
@ -183,6 +186,7 @@ static const struct {
{ "InlineImage", Atom::InlineImage }, { "InlineImage", Atom::InlineImage },
{ "JavaScript", Atom::JavaScript }, { "JavaScript", Atom::JavaScript },
{ "EndJavaScript", Atom::EndJavaScript }, { "EndJavaScript", Atom::EndJavaScript },
{ "Keyword", Atom::Keyword },
{ "LegaleseLeft", Atom::LegaleseLeft }, { "LegaleseLeft", Atom::LegaleseLeft },
{ "LegaleseRight", Atom::LegaleseRight }, { "LegaleseRight", Atom::LegaleseRight },
{ "LineBreak", Atom::LineBreak }, { "LineBreak", Atom::LineBreak },

View File

@ -84,6 +84,7 @@ public:
InlineImage, InlineImage,
JavaScript, JavaScript,
EndJavaScript, EndJavaScript,
Keyword,
LegaleseLeft, LegaleseLeft,
LegaleseRight, LegaleseRight,
LineBreak, LineBreak,

View File

@ -1690,12 +1690,15 @@ void DocParser::insertTarget(const QString &target, bool keyword)
} }
else { else {
targetMap_.insert(target, location()); targetMap_.insert(target, location());
append(Atom::Target, target);
priv->constructExtra(); priv->constructExtra();
if (keyword) if (keyword) {
append(Atom::Keyword, target);
priv->extra->keywords_.append(priv->text.lastAtom()); priv->extra->keywords_.append(priv->text.lastAtom());
else }
else {
append(Atom::Target, target);
priv->extra->targets_.append(priv->text.lastAtom()); priv->extra->targets_.append(priv->text.lastAtom());
}
} }
} }

View File

@ -270,6 +270,20 @@ QString HtmlGenerator::format()
return "HTML"; return "HTML";
} }
/*!
Generate targets for any \keyword commands that were seen
in the qdoc comment for the \a node.
*/
void HtmlGenerator::generateKeywordAnchors(const Node* node)
{
if (!node->doc().isEmpty()) {
const QList<Atom*>& keywords = node->doc().keywords();
foreach (Atom* a, keywords) {
out() << "<a name=\"" << Doc::canonicalTitle(a->string()) << "\"></a>";
}
}
}
/*! /*!
Traverses the current tree generating all the HTML documentation. Traverses the current tree generating all the HTML documentation.
*/ */
@ -1229,6 +1243,8 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
break; break;
case Atom::TableOfContents: case Atom::TableOfContents:
break; break;
case Atom::Keyword:
break;
case Atom::Target: case Atom::Target:
out() << "<a name=\"" << Doc::canonicalTitle(atom->string()) << "\"></a>"; out() << "<a name=\"" << Doc::canonicalTitle(atom->string()) << "\"></a>";
break; break;
@ -1276,8 +1292,10 @@ void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")" << Atom(Atom::LineBreak); subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")" << Atom(Atom::LineBreak);
generateHeader(title, inner, marker); generateHeader(title, inner, marker);
sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay); sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
generateTableOfContents(inner,marker,&sections); generateTableOfContents(inner,marker,&sections);
generateKeywordAnchors(inner);
generateTitle(title, subtitleText, SmallSubTitle, inner, marker); generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
generateBrief(inner, marker); generateBrief(inner, marker);
generateRequisites(inner, marker); generateRequisites(inner, marker);
@ -1450,6 +1468,7 @@ void HtmlGenerator::generateQmlTypePage(QmlClassNode* qcn, CodeMarker* marker)
QList<Section> sections = marker->qmlSections(qcn, CodeMarker::Summary); QList<Section> sections = marker->qmlSections(qcn, CodeMarker::Summary);
generateTableOfContents(qcn, marker, &sections); generateTableOfContents(qcn, marker, &sections);
marker = CodeMarker::markerForLanguage(QLatin1String("QML")); marker = CodeMarker::markerForLanguage(QLatin1String("QML"));
generateKeywordAnchors(qcn);
generateTitle(htmlTitle, Text() << qcn->subTitle(), subTitleSize, qcn, marker); generateTitle(htmlTitle, Text() << qcn->subTitle(), subTitleSize, qcn, marker);
generateBrief(qcn, marker); generateBrief(qcn, marker);
generateQmlRequisites(qcn, marker); generateQmlRequisites(qcn, marker);
@ -1521,6 +1540,7 @@ void HtmlGenerator::generateQmlBasicTypePage(QmlBasicTypeNode* qbtn, CodeMarker*
generateHeader(htmlTitle, qbtn, marker); generateHeader(htmlTitle, qbtn, marker);
QList<Section> sections = marker->sections(qbtn, CodeMarker::Summary, CodeMarker::Okay); QList<Section> sections = marker->sections(qbtn, CodeMarker::Summary, CodeMarker::Okay);
generateTableOfContents(qbtn,marker,&sections); generateTableOfContents(qbtn,marker,&sections);
generateKeywordAnchors(qbtn);
generateTitle(htmlTitle, generateTitle(htmlTitle,
Text() << qbtn->subTitle(), Text() << qbtn->subTitle(),
subTitleSize, subTitleSize,
@ -1567,6 +1587,7 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
(dn->name() != QString("qtexamplesandtutorials.html"))) (dn->name() != QString("qtexamplesandtutorials.html")))
generateTableOfContents(dn,marker,0); generateTableOfContents(dn,marker,0);
generateKeywordAnchors(dn);
generateTitle(fullTitle, generateTitle(fullTitle,
Text() << dn->subTitle(), Text() << dn->subTitle(),
subTitleSize, subTitleSize,
@ -1651,6 +1672,7 @@ void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marke
generateHeader(fullTitle, cn, marker); generateHeader(fullTitle, cn, marker);
generateTableOfContents(cn,marker,0); generateTableOfContents(cn,marker,0);
generateKeywordAnchors(cn);
generateTitle(fullTitle, Text() << cn->subTitle(), subTitleSize, cn, marker); generateTitle(fullTitle, Text() << cn->subTitle(), subTitleSize, cn, marker);
if (cn->isModule()) { if (cn->isModule()) {
@ -3901,6 +3923,7 @@ void HtmlGenerator::generateDetailedMember(const Node *node,
generateMacRef(node, marker); generateMacRef(node, marker);
#endif #endif
generateExtractionMark(node, MemberMark); generateExtractionMark(node, MemberMark);
generateKeywordAnchors(node);
QString nodeRef = refForNode(node); QString nodeRef = refForNode(node);
if (node->type() == Node::Enum if (node->type() == Node::Enum
&& (enume = static_cast<const EnumNode *>(node))->flagsType()) { && (enume = static_cast<const EnumNode *>(node))->flagsType()) {
@ -4137,6 +4160,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
generateMacRef(node, marker); generateMacRef(node, marker);
#endif #endif
generateExtractionMark(node, MemberMark); generateExtractionMark(node, MemberMark);
generateKeywordAnchors(node);
out() << "<div class=\"qmlitem\">"; out() << "<div class=\"qmlitem\">";
QString nodeRef = refForNode(node); QString nodeRef = refForNode(node);
if (node->type() == Node::QmlPropertyGroup) { if (node->type() == Node::QmlPropertyGroup) {

View File

@ -105,6 +105,7 @@ protected:
void generateManifestFile(QString manifest, QString element); void generateManifestFile(QString manifest, QString element);
void readManifestMetaContent(const Config &config); void readManifestMetaContent(const Config &config);
void generateKeywordAnchors(const Node* node);
private: private:
enum SubTitleSize { SmallSubTitle, LargeSubTitle }; enum SubTitleSize { SmallSubTitle, LargeSubTitle };

View File

@ -1135,7 +1135,7 @@ QString Tree::refForAtom(const Atom* atom)
if (atom) { if (atom) {
if (atom->type() == Atom::SectionLeft) if (atom->type() == Atom::SectionLeft)
return Doc::canonicalTitle(Text::sectionHeading(atom).toString()); return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
if (atom->type() == Atom::Target) if ((atom->type() == Atom::Target) || (atom->type() == Atom::Keyword))
return Doc::canonicalTitle(atom->string()); return Doc::canonicalTitle(atom->string());
} }
return QString(); return QString();