Try to be smarter about adding links to section titles

When adding links, don't add them around other links. If there's
anything outside of existing links, they'll still get linked. Although,
maybe it would be better to only add link tags when the title doesn't
contain any links. This might be over-complicated and confusing.
This commit is contained in:
Daniel James
2017-05-11 12:55:00 +01:00
parent 5f8e2a9f5a
commit 9d98653e9b
7 changed files with 170 additions and 4 deletions

View File

@@ -1754,10 +1754,7 @@ namespace quickbook
if (self_linked_headers && state.document.compatibility_version() >= 103)
{
state.out << "<link linkend=\"" << full_id << "\">"
<< content.get_encoded()
<< "</link>"
;
state.out << quickbook::detail::linkify(content.get_encoded(), full_id);
}
else
{

View File

@@ -150,4 +150,127 @@ namespace quickbook
c.finish(source);
}
namespace detail {
std::string linkify(quickbook::string_view source, quickbook::string_view linkend)
{
typedef quickbook::string_view::const_iterator iterator;
std::string result;
iterator it = source.begin(), end = source.end();
int link_depth = 0;
iterator start = it;
read_some_of(it, end, " \t\n\r");
result.append(start, it);
start = it;
// If the source is empty, we'll still create an empty link tag
// to avoid gratuitous changes in generated output, need to track
// that special case.
bool empty = true;
for(;;)
{
read_to_one_of(it, end, "<");
if (it == end) break;
iterator tag_start = it;
++it;
if (it == end) break;
if (read(it, end, "!--quickbook-escape-prefix-->"))
{
read_past(it, end, "<!--quickbook-escape-postfix-->");
continue;
}
switch(*it)
{
case '?':
++it;
read_past(it, end, "?>");
break;
case '!':
if (read(it, end, "!--")) {
read_past(it, end, "-->");
} else {
read_past(it, end, ">");
}
break;
case '/':
{
++it;
read_some_of(it, end, " \t\n\r");
if (it == end) { break; }
iterator tag_name_start = it;
read_to_one_of(it, end, " \t\n\r>");
quickbook::string_view tag_name(tag_name_start, it - tag_name_start);
read_past(it, end, ">");
if (tag_name == "link") {
if (link_depth > 0) { --link_depth; }
if (link_depth == 0) {
read_some_of(it, end, " \t\n\r");
result.append(start, it);
start = it;
empty = false;
}
}
}
break;
default:
if ((*it >= 'a' && *it <= 'z') ||
(*it >= 'A' && *it <= 'Z') ||
*it == '_' || *it == ':')
{
iterator tag_name_start = it;
read_to_one_of(it, end, " \t\n\r>");
quickbook::string_view tag_name(tag_name_start, it - tag_name_start);
if (tag_name == "link") {
if (link_depth == 0 && start != tag_start) {
result += "<link linkend=\"";
result .append(linkend.begin(), linkend.end());
result += "\">";
result.append(start, tag_start);
result += "</link>";
start = tag_start;
empty = false;
}
++link_depth;
}
for (;;) {
read_to_one_of(it, end, "\"'\n\r>");
if (it == end || *it == '>') break;
if (*it == '"' || *it == '\'') {
char delim = *it;
++it;
it = std::find(it, end, delim);
if (it == end) break;
++it;
}
}
}
else
{
read_past(it, end, ">");
}
}
}
if (start != it || empty) {
result += "<link linkend=\"";
result.append(linkend.begin(), linkend.end());
result += "\">";
result.append(start, it);
result += "</link>";
}
return result;
}
}
}

View File

@@ -49,6 +49,9 @@ namespace quickbook { namespace detail {
inline std::string to_s(quickbook::string_view x) {
return std::string(x.begin(), x.end());
}
// Defined in id_xml.cpp. Just because.
std::string linkify(quickbook::string_view source, quickbook::string_view linkend);
}}
#endif // BOOST_SPIRIT_QUICKBOOK_UTILS_HPP

View File

@@ -23,4 +23,11 @@
<section id="section_id_1_7.sect-abc">
<title><link linkend="section_id_1_7.sect-abc">Section with template in id</link></title>
</section>
<section id="section_id_1_7.link_section_id_1_7_id_test1_lin">
<title><link linkend="section_id_1_7.id_test1">Link in title</link></title>
</section>
<section id="section_id_1_7.link_section_id_1_7_id_test1_li0">
<title><link linkend="section_id_1_7.id_test1">Link</link> <link linkend="section_id_1_7.link_section_id_1_7_id_test1_li0">in
title</link></title>
</section>
</article>

View File

@@ -16,3 +16,8 @@
[template thing[] abc]
[section:sect-[thing] Section with template in id]
[endsect]
[section [link section_id_1_7.id_test1 Link in title]]
[endsect]
[section [link section_id_1_7.id_test1 Link] in title]
[endsect]

View File

@@ -22,6 +22,7 @@ run values_test.cpp ../../src/values.cpp ../../src/files.cpp ;
run post_process_test.cpp ../../src/post_process.cpp ;
run source_map_test.cpp ../../src/files.cpp ;
run glob_test.cpp ../../src/glob.cpp ;
run linkify_test.cpp ../../src/id_xml.cpp ;
# TODO: Reinstate this test? Too painful to run at the moment.
# run file_path_to_url_test.cpp ../../src/native_text.cpp ../../src/utils.cpp ;

View File

@@ -0,0 +1,30 @@
/*=============================================================================
Copyright (c) 2017 Daniel James
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#include "utils.hpp"
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
void linkify_test() {
using quickbook::detail::linkify;
BOOST_TEST(linkify("abc", "link") == "<link linkend=\"link\">abc</link>");
BOOST_TEST(linkify("<link linkend=\"something\">abc</link>", "link") ==
"<link linkend=\"something\">abc</link>");
BOOST_TEST(linkify("abc <link linkend=\"something\">def</link>", "link") ==
"<link linkend=\"link\">abc </link><link linkend=\"something\">def</link>");
BOOST_TEST(linkify("<link linkend=\"something\">abc</link> def", "link") ==
"<link linkend=\"something\">abc</link> <link linkend=\"link\">def</link>");
}
int main() {
linkify_test();
return boost::report_errors();
}