diff --git a/Jamfile.v2 b/Jamfile.v2
index 0df2fa9..64a0ab0 100644
--- a/Jamfile.v2
+++ b/Jamfile.v2
@@ -33,3 +33,13 @@ install dist-lib
:
release
;
+
+# Target for quickbook toolset's auto build.
+
+alias quickbook-auto
+ : quickbook
+ : release
+ ;
+
+explicit quickbook-auto
+ ;
diff --git a/src/Jamfile.v2 b/src/Jamfile.v2
index 736c19f..7b6460c 100644
--- a/src/Jamfile.v2
+++ b/src/Jamfile.v2
@@ -28,6 +28,7 @@ exe quickbook
utils.cpp
input_path.cpp
values.cpp
+ id_generator.cpp
post_process.cpp
collector.cpp
template_stack.cpp
diff --git a/src/actions.cpp b/src/actions.cpp
index 5023d8c..bea5cb7 100644
--- a/src/actions.cpp
+++ b/src/actions.cpp
@@ -29,6 +29,7 @@
#include "input_path.hpp"
#include "block_tags.hpp"
#include "phrase_tags.hpp"
+#include "id_generator.hpp"
namespace quickbook
{
@@ -58,12 +59,23 @@ namespace quickbook
it != end; ++it)
{
tgt << " ";
}
actions.anchors.clear();
- }
+ }
+
+ std::string add_anchor(quickbook::actions& actions,
+ std::string const& id,
+ id_generator::categories category = id_generator::explicit_id)
+ {
+ std::string placeholder = actions.ids.add(id, category);
+ actions.anchors.push_back(placeholder);
+ return placeholder;
+ }
}
void list_action(quickbook::actions&, value);
@@ -261,8 +273,7 @@ namespace quickbook
value_consumer values = phrase;
actions.phrase
<< "(actions.footnote_id_count++)
+ << actions.ids.add(actions.doc_id + ".f", id_generator::numbered)
<< "\">"
<< values.consume().get_boostbook()
<< " ";
@@ -297,27 +308,31 @@ namespace quickbook
}
namespace {
- void write_bridgehead(collector& out, int level,
+ void write_bridgehead(quickbook::actions& actions, int level,
std::string const& str, std::string const& id, bool self_link)
{
if (self_link && !id.empty())
{
- out << "";
- out << " ";
- out << " ";
- out << str;
- out << "";
- out << " ";
+ actions.out << "";
+ actions.out << " ";
+ actions.out << " ";
+ actions.out << str;
+ actions.out << "";
+ actions.out << " ";
}
else
{
- out << "";
- out << str;
- out << " ";
+ actions.out << "";
+ actions.out << str;
+ actions.out << " ";
}
}
}
@@ -347,20 +362,26 @@ namespace quickbook
level = heading_list.get_tag() - block_tags::heading1 + 1;
}
- std::string anchor;
write_anchors(actions, actions.out);
if (!generic && qbk_version_n < 103) // version 1.2 and below
{
- anchor = actions.section_id + '.' +
- detail::make_identifier(content.get_boostbook());
+ std::string anchor = actions.ids.add(
+ actions.section_id + '.' +
+ detail::make_identifier(content.get_boostbook()),
+ id_generator::generated);
- write_bridgehead(actions.out, level,
+ write_bridgehead(actions, level,
content.get_boostbook(), anchor, false);
}
else
{
+ id_generator::categories category =
+ !element_id.empty() ?
+ id_generator::explicit_id :
+ id_generator::generated;
+
std::string id =
!element_id.empty() ?
element_id.get_quickbook() :
@@ -370,13 +391,14 @@ namespace quickbook
content.get_boostbook()
);
- anchor = fully_qualified_id(actions.doc_id,
- actions.qualified_section_id, id);
+ std::string anchor = actions.ids.add(
+ fully_qualified_id(actions.doc_id,
+ actions.qualified_section_id, id),
+ category);;
- write_bridgehead(actions.out, level,
+ write_bridgehead(actions, level,
content.get_boostbook(), anchor, true);
}
-
}
void simple_phrase_action::operator()(char mark) const
@@ -588,7 +610,7 @@ namespace quickbook
void anchor_action(quickbook::actions& actions, value anchor)
{
value_consumer values = anchor;
- actions.anchors.push_back(values.consume().get_quickbook());
+ add_anchor(actions, values.consume().get_quickbook());
values.finish();
}
@@ -1101,8 +1123,7 @@ namespace quickbook
while (arg != args.end())
{
if (!actions.templates.add(
- template_symbol(*tpl, empty_params, arg->content,
- arg->filename, &scope)))
+ template_symbol(*tpl, empty_params, *arg, &scope)))
{
detail::outerr(actions.filename, pos.line)
<< "Duplicate Symbol Found" << std::endl;
@@ -1127,7 +1148,8 @@ namespace quickbook
//
// Note: this is now done in the grammar.
- if (escape)
+ // TODO: For escape, should this be surrounded in escape comments?
+ if (body.type == template_body::raw_output || escape)
{
// escape the body of the template
// we just copy out the literal body
@@ -1247,24 +1269,31 @@ namespace quickbook
file_position pos)
{
assert(symbol->body.is_block());
-
+
+ std::vector callout_ids;
std::vector args;
unsigned int size = symbol->params.size();
for(unsigned int i = 0; i < size; ++i)
{
- std::string callout_id = actions.doc_id +
- boost::lexical_cast(actions.callout_id_count + i);
+ std::string callout_id1 =
+ actions.ids.add(
+ actions.doc_id + ".c",
+ id_generator::numbered);
+ std::string callout_id2 =
+ actions.ids.add(
+ actions.doc_id + ".c",
+ id_generator::numbered);
std::string code;
- code += "'''";
- code += " ";
- code += "'''";
+ code += " ";
args.push_back(template_body(
qbk_value(code, pos, template_tags::phrase),
- actions.filename));
+ actions.filename, template_body::raw_output));
+ callout_ids.push_back(callout_id1);
+ callout_ids.push_back(callout_id2);
}
call_template(actions, template_escape, symbol, args, pos);
@@ -1277,10 +1306,11 @@ namespace quickbook
++actions.template_depth;
block += "";
+ int i = 0;
BOOST_FOREACH(value c, symbol->callouts)
{
- std::string callout_id = actions.doc_id +
- boost::lexical_cast(actions.callout_id_count++);
+ std::string callout_id1 = callout_ids[i++];
+ std::string callout_id2 = callout_ids[i++];
std::string callout_value;
{
@@ -1304,8 +1334,8 @@ namespace quickbook
actions.out.swap(callout_value);
}
- block += "";
+ block += "";
block += callout_value;
block += " ";
}
@@ -1326,6 +1356,7 @@ namespace quickbook
std::string identifier = values.consume(template_tags::identifier).get_quickbook();
+ std::vector callout_ids;
std::vector args;
BOOST_FOREACH(value arg, values)
@@ -1444,15 +1475,26 @@ namespace quickbook
std::string table_id;
if(qbk_version_n >= 105) {
if(!element_id.empty()) {
- table_id = fully_qualified_id(actions.doc_id,
- actions.qualified_section_id, element_id);
+ table_id = actions.ids.add(
+ fully_qualified_id(actions.doc_id,
+ actions.qualified_section_id, element_id),
+ id_generator::explicit_id);
}
else if(has_title) {
- table_id = fully_qualified_id(actions.doc_id,
- actions.qualified_section_id,
- detail::make_identifier(title));
+ table_id = actions.ids.add(
+ fully_qualified_id(actions.doc_id,
+ actions.qualified_section_id,
+ detail::make_identifier(title)),
+ id_generator::generated);
}
}
+ else if (has_title)
+ {
+ table_id = actions.ids.add(
+ fully_qualified_id(actions.doc_id,
+ actions.qualified_section_id, "t"),
+ id_generator::numbered);
+ }
// Emulating the old behaviour which used the width of the final
// row for span_count.
@@ -1540,17 +1582,17 @@ namespace quickbook
actions.qualified_section_id += actions.section_id;
++actions.section_level;
- if (qbk_version_n < 103) // version 1.2 and below
- {
- actions.out << "\n\n";
- }
- else // version 1.3 and above
- {
- actions.out << "\n\n";
- }
+ // TODO: This could be awkward if there's a clash, possibly
+ // needs another category, between explicit and generated.
+ std::string full_id = actions.ids.add(
+ qbk_version_n < 103 ?
+ actions.doc_id + "." + actions.section_id :
+ actions.doc_id + "." + actions.qualified_section_id,
+ !element_id.empty() ?
+ id_generator::explicit_id :
+ id_generator::generated);
+ actions.out << "\n\n";
actions.out << "";
write_anchors(actions, actions.out);
@@ -1561,8 +1603,7 @@ namespace quickbook
}
else // version 1.3 and above
{
- actions.out << " "
+ actions.out << " "
<< content.get_boostbook()
<< ""
;
diff --git a/src/actions_class.cpp b/src/actions_class.cpp
index 002f6e7..420955c 100644
--- a/src/actions_class.cpp
+++ b/src/actions_class.cpp
@@ -19,7 +19,8 @@
namespace quickbook
{
- actions::actions(fs::path const& filein_, fs::path const& xinclude_base_, string_stream& out_)
+ actions::actions(fs::path const& filein_, fs::path const& xinclude_base_,
+ string_stream& out_, id_generator& ids)
: grammar_()
, doc_title_qbk()
@@ -32,8 +33,7 @@ namespace quickbook
, warned_about_breaks(false)
, context(0)
, conditional(true)
- , callout_id_count(0)
- , footnote_id_count(0)
+ , ids(ids)
, imported(false)
, doc_type()
diff --git a/src/actions_class.hpp b/src/actions_class.hpp
index ce58cd9..f71652d 100644
--- a/src/actions_class.hpp
+++ b/src/actions_class.hpp
@@ -23,7 +23,8 @@ namespace quickbook
struct actions
{
- actions(fs::path const& filein_, fs::path const& xinclude_base, string_stream& out_);
+ actions(fs::path const& filein_, fs::path const& xinclude_base, string_stream& out_,
+ id_generator&);
private:
boost::scoped_ptr grammar_;
@@ -47,8 +48,7 @@ namespace quickbook
bool warned_about_breaks;
int context;
bool conditional;
- int callout_id_count;
- int footnote_id_count;
+ id_generator& ids;
// state saved for files and templates.
bool imported;
diff --git a/src/block_element_grammar.cpp b/src/block_element_grammar.cpp
index 6732979..e246fad 100644
--- a/src/block_element_grammar.cpp
+++ b/src/block_element_grammar.cpp
@@ -34,7 +34,8 @@ namespace quickbook
xinclude, include,
template_, template_id, template_formal_arg,
template_body, identifier, import,
- element_id, element_id_1_5, element_id_1_6;
+ element_id, element_id_1_5, element_id_1_6,
+ same_line;
};
void quickbook_grammar::impl::init_block_elements()
@@ -44,7 +45,7 @@ namespace quickbook
local.element_id =
!( ':'
- >> ( cl::if_p(qbk_since(105u)) [space]
+ >> ( !(cl::eps_p(qbk_since(105u)) >> space)
>> (+(cl::alnum_p | '_')) [actions.values.entry(ph::arg1, ph::arg2, general_tags::element_id)]
| cl::eps_p [actions.element_id_warning]
)
@@ -52,16 +53,10 @@ namespace quickbook
;
local.element_id_1_5 =
- cl::if_p(qbk_since(105u)) [
- local.element_id
- ]
- ;
+ !(cl::eps_p(qbk_since(105u)) >> local.element_id);
local.element_id_1_6 =
- cl::if_p(qbk_since(106u)) [
- local.element_id
- ]
- ;
+ !(cl::eps_p(qbk_since(106u)) >> local.element_id);
elements.add
("section", element_info(element_info::block, &local.begin_section, block_tags::begin_section))
@@ -208,10 +203,12 @@ namespace quickbook
("table", element_info(element_info::nested_block, &local.table, block_tags::table))
;
+ local.same_line = (cl::eps_p(*cl::blank_p >> cl::eol_p) | space);
+
local.table =
- (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
+ local.same_line
>> local.element_id_1_5
- >> (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
+ >> local.same_line
>> (*(cl::anychar_p - eol)) [actions.values.entry(ph::arg1, ph::arg2, table_tags::title)]
>> (+eol)
>> *local.table_row
diff --git a/src/doc_info_actions.cpp b/src/doc_info_actions.cpp
index cd4d2ea..edee209 100644
--- a/src/doc_info_actions.cpp
+++ b/src/doc_info_actions.cpp
@@ -17,6 +17,7 @@
#include "input_path.hpp"
#include "actions_class.hpp"
#include "doc_info_tags.hpp"
+#include "id_generator.hpp"
namespace quickbook
{
@@ -280,7 +281,7 @@ namespace quickbook
out << '<' << actions.doc_type << "\n"
<< " id=\""
- << actions.doc_id
+ << actions.ids.add(actions.doc_id, id_generator::explicit_id)
<< "\"\n"
;
@@ -374,7 +375,10 @@ namespace quickbook
if (!license.empty())
{
- tmp << " \n"
+ tmp << " \n"
<< " \n"
<< " " << doc_info_output(license, 103) << "\n"
<< " \n"
diff --git a/src/fwd.hpp b/src/fwd.hpp
index 60d246d..1b63611 100644
--- a/src/fwd.hpp
+++ b/src/fwd.hpp
@@ -18,6 +18,7 @@ namespace quickbook
struct actions;
struct quickbook_grammar;
struct collector;
+ struct id_generator;
typedef position_iterator iterator;
diff --git a/src/id_generator.cpp b/src/id_generator.cpp
new file mode 100644
index 0000000..571853e
--- /dev/null
+++ b/src/id_generator.cpp
@@ -0,0 +1,349 @@
+/*=============================================================================
+ Copyright (c) 2011 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 "id_generator.hpp"
+#include "markups.hpp"
+#include "phrase_tags.hpp"
+#include
+#include
+#include
+
+namespace quickbook
+{
+ // string_ref
+
+ class string_ref
+ {
+ public:
+ typedef std::string::const_iterator iterator;
+
+ private:
+ iterator begin_, end_;
+
+ public:
+ string_ref() : begin_(), end_() {}
+
+ explicit string_ref(iterator b, iterator e)
+ : begin_(b), end_(e) {}
+
+ explicit string_ref(std::string const& x)
+ : begin_(x.begin()), end_(x.end()) {}
+
+ iterator begin() const { return begin_; }
+ iterator end() const { return end_; }
+
+ std::size_t size() const
+ {
+ return static_cast(end_ - begin_);
+ }
+ };
+
+ bool operator==(string_ref const& x, string_ref const& y);
+ bool operator<(string_ref const& x, string_ref const& y);
+
+ inline bool operator==(string_ref const& x, std::string const& y)
+ {
+ return x == string_ref(y);
+ }
+
+ inline bool operator==(std::string const& x, string_ref const& y)
+ {
+ return string_ref(x) == y;
+ }
+
+ inline bool operator<(string_ref const& x, std::string const& y)
+ {
+ return x < string_ref(y);
+ }
+
+ inline bool operator<(std::string const& x, string_ref const& y)
+ {
+ return string_ref(x) < y;
+ }
+
+ bool operator==(string_ref const& x, string_ref const& y)
+ {
+ return x.size() == y.size() &&
+ std::equal(x.begin(), x.end(), y.begin());
+ }
+
+ bool operator<(string_ref const& x, string_ref const& y)
+ {
+ return std::lexicographical_compare(
+ x.begin(), x.end(), y.begin(), y.end());
+ }
+
+ // id_generator
+
+ struct id_generator::id
+ {
+ id()
+ : category(id_generator::default_category),
+ used(false),
+ count(0) {}
+
+ id_generator::categories category;
+
+ // These are updated when generating ids
+ bool used;
+ int count;
+ };
+
+ struct id_generator::placeholder
+ {
+ typedef std::pair id_pair;
+
+ placeholder(id_generator::categories category, id_pair& id)
+ : category(category),
+ id(id),
+ final_id() {}
+
+ id_generator::categories category;
+ id_pair& id;
+ std::string final_id; // Set in the second pass.
+ };
+
+ id_generator::id_generator()
+ {
+ }
+
+ id_generator::~id_generator()
+ {
+ }
+
+ std::string id_generator::add(
+ std::string const& value,
+ id_generator::categories category)
+ {
+ std::string result;
+ id_generator::id& id = ids_[value];
+
+ // Doesn't check if explicit ids collide, could probably be a warning.
+ if (category == explicit_id)
+ {
+ id.category = category;
+ id.used = true;
+ result = value;
+ }
+ else
+ {
+ if (category < id.category) id.category = category;
+
+ // '$' can't appear in quickbook ids, so use it indicate a
+ // placeholder id.
+ result = "$" +
+ boost::lexical_cast(placeholders_.size());
+ placeholders_.push_back(
+ id_generator::placeholder(category, *ids_.find(value)));
+ }
+
+ return result;
+ }
+
+ string_ref id_generator::get(string_ref value)
+ {
+ // If this isn't a placeholder id.
+ if (value.size() <= 1 || *value.begin() != '$')
+ return value;
+
+ id_generator::placeholder& placeholder = placeholders_.at(
+ boost::lexical_cast(std::string(
+ value.begin() + 1, value.end())));
+
+ if (placeholder.final_id.empty())
+ {
+ if (placeholder.category < id_generator::numbered &&
+ !placeholder.id.second.used &&
+ placeholder.id.second.category == placeholder.category)
+ {
+ placeholder.id.second.used = true;
+ placeholder.final_id = placeholder.id.first;
+ }
+ else while(true)
+ {
+ int count = placeholder.id.second.count++;
+ placeholder.final_id = placeholder.id.first +
+ boost::lexical_cast(count);
+ // TODO: Should add final_id to ids_, there are some
+ // edges cases where it could collide.
+ if (ids_.find(placeholder.final_id) == ids_.end())
+ break;
+ }
+ }
+
+ return string_ref(placeholder.final_id);
+ }
+
+ // Very simple xml subset parser which replaces id values.
+ //
+ // I originally tried to integrate this into the post processor
+ // but that proved tricky. Alternatively it could use a proper
+ // xml parser, but I want this to be able to survive badly
+ // marked up escapes.
+
+ struct xml_processor
+ {
+ xml_processor();
+
+ std::string escape_prefix;
+ std::string escape_postfix;
+ std::string processing_instruction_postfix;
+ std::string comment_postfix;
+ std::string tag_end;
+ std::string name_end;
+ std::vector id_attributes;
+
+ std::string replace(std::string const&, id_generator&);
+ };
+
+ std::string id_generator::replace_placeholders(std::string const& source)
+ {
+ xml_processor processor;
+ return processor.replace(source, *this);
+ }
+
+ namespace
+ {
+ char const* id_attributes_[] =
+ {
+ "id",
+ "linkend",
+ "linkends",
+ "arearefs"
+ };
+ }
+
+ xml_processor::xml_processor()
+ : escape_prefix("!--quickbook-escape-prefix-->")
+ , escape_postfix("!--quickbook-escape-postfix-->")
+ , processing_instruction_postfix("?>")
+ , comment_postfix("-->")
+ , tag_end(" \t\n\r>")
+ , name_end("= \t\n\r>")
+ {
+ static int const n_id_attributes = sizeof(id_attributes_)/sizeof(char const*);
+ for (int i = 0; i != n_id_attributes; ++i)
+ {
+ id_attributes.push_back(id_attributes_[i]);
+ }
+
+ std::sort(id_attributes.begin(), id_attributes.end());
+ }
+
+ std::string xml_processor::replace(std::string const& source, id_generator& ids)
+ {
+ std::string result;
+
+ typedef std::string::const_iterator iterator;
+ iterator pos = source.begin(), end = source.end();
+ iterator next = pos;
+
+ while (true) {
+ next = std::find(next, end, '<');
+ if (next == end) break;
+
+ if (end - pos > escape_prefix.size() && std::equal(
+ escape_prefix.begin(), escape_prefix.end(), pos))
+ {
+ next = std::search(next + escape_prefix.size(), end,
+ escape_postfix.begin(), escape_postfix.end());
+
+ if (next == end) break;
+
+ next += escape_postfix.size();
+ continue;
+ }
+
+ ++next;
+ if (next == end) break;
+
+ switch(*next)
+ {
+ case '?':
+ next = std::search(next, end,
+ processing_instruction_postfix.begin(),
+ processing_instruction_postfix.end());
+
+ if (next != end) next += processing_instruction_postfix.size();
+ break;
+ case '!':
+ if (end - next > 3 && next[1] == '-' && next[2] == '-')
+ {
+ next = std::search(next + 3, end,
+ comment_postfix.begin(), comment_postfix.end());
+
+ if (next != end) next += comment_postfix.size();
+ }
+ else
+ {
+ next = std::find(next + 1, end, '>');
+ if (next != end) ++next;
+ }
+ break;
+ default:
+ if (*next >= 'a' || *next <= 'z' ||
+ *next >= 'A' || *next <= 'Z' ||
+ *next == '_' || *next == ':')
+ {
+ next = std::find_first_of(
+ next + 1, end, tag_end.begin(), tag_end.end());
+
+ while (true) {
+ while(next != end && (*next == ' ' || *next == '\t'))
+ ++next;
+
+ iterator name_start = next;
+
+ next = std::find_first_of(
+ next, end, name_end.begin(), name_end.end());
+
+ if (next == end || *next == '>') break;
+
+ string_ref name(name_start, next);
+ ++next;
+
+ while (next != end &&
+ std::find(name_end.begin(), name_end.end(), *next)
+ != name_end.end())
+ ++next;
+
+ if (next == end || (*next != '"' && *next != '\'')) break;
+
+ char delim = *next;
+ ++next;
+
+ iterator value_start = next;
+
+ next = std::find(next, end, delim);
+ string_ref value(value_start, next);
+ if (next == end) break;
+ ++next;
+
+ if (std::find(id_attributes.begin(),
+ id_attributes.end(), name)
+ != id_attributes.end())
+ {
+ result.append(pos, value.begin());
+ string_ref x = ids.get(value);
+ result.append(x.begin(), x.end());
+ pos = value.end();
+ }
+ }
+ }
+ else
+ {
+ next = std::find(next + 1, end, '>');
+ if (next != end) ++next;
+ }
+ }
+ }
+
+ result.append(pos, source.end());
+ return result;
+ }
+}
diff --git a/src/id_generator.hpp b/src/id_generator.hpp
new file mode 100644
index 0000000..9995b0c
--- /dev/null
+++ b/src/id_generator.hpp
@@ -0,0 +1,53 @@
+/*=============================================================================
+ Copyright (c) 2011 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)
+=============================================================================*/
+
+#if !defined(BOOST_QUICKBOOK_ID_GENERATOR_HPP)
+#define BOOST_QUICKBOOK_ID_GENERATOR_HPP
+
+#include "fwd.hpp"
+#include
+#include
+#include
+
+namespace quickbook
+{
+ class string_ref;
+
+ class id_generator
+ {
+ public:
+
+ enum categories
+ {
+ explicit_id = 0, // Explicitly given by user
+ generated, // Generated from source, e.g. table title
+ numbered, // Just used to avoid random docbook ids
+ default_category
+ };
+
+ private:
+
+ struct id;
+ struct placeholder;
+ typedef boost::unordered_map placeholder_map;
+
+ placeholder_map ids_;
+ std::deque placeholders_;
+
+ public:
+ id_generator();
+ ~id_generator();
+
+ std::string add(std::string const& id, categories priority);
+
+ std::string replace_placeholders(std::string const&);
+ string_ref get(string_ref placeholder);
+ };
+}
+
+#endif
\ No newline at end of file
diff --git a/src/main_grammar.cpp b/src/main_grammar.cpp
index 56776ea..d3a210a 100644
--- a/src/main_grammar.cpp
+++ b/src/main_grammar.cpp
@@ -145,9 +145,7 @@ namespace quickbook
actions.scoped_context(element_info::in_block)
[ local.blocks
>> *( local.element
- >> cl::if_p(local.is_block)
- [ !(+eol >> local.blocks)
- ]
+ >> !(cl::eps_p(local.is_block) >> +eol >> local.blocks)
| local.paragraph_separator >> local.blocks
| common
| cl::space_p [actions.space_char]
@@ -282,11 +280,10 @@ namespace quickbook
;
local.template_args =
- cl::if_p(qbk_since(105u)) [
- local.template_args_1_5
- ].else_p [
- local.template_args_1_4
- ]
+ cl::eps_p(qbk_since(105u))
+ >> local.template_args_1_5
+ | cl::eps_p(qbk_before(105u))
+ >> local.template_args_1_4
;
local.template_args_1_4 = local.template_arg_1_4 >> *(".." >> local.template_arg_1_4);
diff --git a/src/phrase_element_grammar.cpp b/src/phrase_element_grammar.cpp
index ab5de65..b2e4821 100644
--- a/src/phrase_element_grammar.cpp
+++ b/src/phrase_element_grammar.cpp
@@ -51,28 +51,28 @@ namespace quickbook
;
local.image =
- blank
- >> cl::if_p(qbk_since(105u)) [
- (+(
- *cl::space_p
- >> +(cl::anychar_p - (cl::space_p | phrase_end | '['))
- )) [actions.values.entry(ph::arg1, ph::arg2)]
- >> hard_space
- >> *actions.values.list()
- [ '['
- >> (*(cl::alnum_p | '_'))
- [actions.values.entry(ph::arg1, ph::arg2)]
- >> space
- >> (*(cl::anychar_p - (phrase_end | '[')))
- [actions.values.entry(ph::arg1, ph::arg2)]
- >> ']'
- >> space
- ]
- ].else_p [
- (*(cl::anychar_p - phrase_end))
- [actions.values.entry(ph::arg1, ph::arg2)]
+ cl::eps_p(qbk_since(105u))
+ >> blank
+ >> (+(
+ *cl::space_p
+ >> +(cl::anychar_p - (cl::space_p | phrase_end | '['))
+ )) [actions.values.entry(ph::arg1, ph::arg2)]
+ >> hard_space
+ >> *actions.values.list()
+ [ '['
+ >> (*(cl::alnum_p | '_'))
+ [actions.values.entry(ph::arg1, ph::arg2)]
+ >> space
+ >> (*(cl::anychar_p - (phrase_end | '[')))
+ [actions.values.entry(ph::arg1, ph::arg2)]
+ >> ']'
+ >> space
]
>> cl::eps_p(']')
+ | cl::eps_p(qbk_before(105u))
+ >> blank
+ >> (*(cl::anychar_p - phrase_end)) [actions.values.entry(ph::arg1, ph::arg2)]
+ >> cl::eps_p(']')
;
elements.add
diff --git a/src/quickbook.cpp b/src/quickbook.cpp
index f8d4fa5..56f74d4 100644
--- a/src/quickbook.cpp
+++ b/src/quickbook.cpp
@@ -13,6 +13,7 @@
#include "post_process.hpp"
#include "utils.hpp"
#include "input_path.hpp"
+#include "id_generator.hpp"
#include
#include
#include
@@ -120,12 +121,8 @@ namespace quickbook
static int
parse_document(
fs::path const& filein_,
- fs::path const& xinclude_base,
- string_stream& out)
- {
- actions actor(filein_, xinclude_base, out);
-
- set_macros(actor);
+ actions& actor)
+ {
try {
parse_file(filein_, actor);
@@ -158,9 +155,14 @@ namespace quickbook
, int linewidth
, bool pretty_print)
{
- int result = 0;
string_stream buffer;
- result = parse_document(filein_, xinclude_base_, buffer);
+ id_generator ids;
+ actions actor(filein_, xinclude_base_, buffer, ids);
+ set_macros(actor);
+
+ int result = parse_document(filein_, actor);
+
+ std::string stage2 = ids.replace_placeholders(buffer.str());
if (result == 0)
{
@@ -170,7 +172,7 @@ namespace quickbook
{
try
{
- fileout << post_process(buffer.str(), indent, linewidth);
+ fileout << post_process(stage2, indent, linewidth);
}
catch (quickbook::post_process_failure&)
{
@@ -178,13 +180,13 @@ namespace quickbook
::quickbook::detail::outerr()
<< "Post Processing Failed."
<< std::endl;
- fileout << buffer.str();
+ fileout << stage2;
return 1;
}
}
else
{
- fileout << buffer.str();
+ fileout << stage2;
}
}
return result;
diff --git a/src/template_stack.cpp b/src/template_stack.cpp
index a2059c3..e6d916a 100644
--- a/src/template_stack.cpp
+++ b/src/template_stack.cpp
@@ -18,10 +18,12 @@ namespace quickbook
{
template_body::template_body(
value const& content,
- fs::path const& filename
+ fs::path const& filename,
+ content_type type
)
: content(content)
, filename(filename)
+ , type(type)
{
assert(content.get_tag() == template_tags::block ||
content.get_tag() == template_tags::phrase);
@@ -32,7 +34,6 @@ namespace quickbook
return content.get_tag() == template_tags::block;
}
-
template_stack::template_stack()
: scope(template_stack::parser(*this))
, scopes()
diff --git a/src/template_stack.hpp b/src/template_stack.hpp
index c053c71..eedee15 100644
--- a/src/template_stack.hpp
+++ b/src/template_stack.hpp
@@ -28,11 +28,18 @@ namespace quickbook
struct template_body
{
- template_body(value const&, fs::path const&);
+ enum content_type
+ {
+ quickbook,
+ raw_output
+ };
+
+ template_body(value const&, fs::path const&, content_type = quickbook);
bool is_block() const;
stored_value content;
fs::path filename;
+ content_type type;
};
struct template_scope;
@@ -40,6 +47,17 @@ namespace quickbook
struct template_symbol
{
template_symbol(
+ std::string const& identifier,
+ std::vector const& params,
+ template_body const& body,
+ template_scope const* parent = 0)
+ : identifier(identifier)
+ , params(params)
+ , body(body)
+ , parent(parent)
+ , callouts() {}
+
+ template_symbol(
std::string const& identifier,
std::vector const& params,
value const& content,
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index b719e9d..9c92582 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -52,6 +52,7 @@ test-suite quickbook.test :
[ quickbook-test identifier_1_6 ]
[ quickbook-test para-test ]
[ quickbook-test variablelist ]
+ [ quickbook-test table_1_3 ]
[ quickbook-test table_1_5 ]
[ quickbook-test image_1_5 ]
[ quickbook-test list_test ]
diff --git a/test/anchor.gold b/test/anchor.gold
index f95738a..ab7453c 100644
--- a/test/anchor.gold
+++ b/test/anchor.gold
@@ -9,24 +9,24 @@
A paragraph containing several anchors. We
want to make sure they appear in the correct place.
-
+
This
heading shouldn't pick up the previous anchor
-
+
This
heading should pick up the previous anchor
-
+
And
this one
-
+
Also
this one
diff --git a/test/blocks.gold b/test/blocks.gold
index 2306736..2d7370b 100644
--- a/test/blocks.gold
+++ b/test/blocks.gold
@@ -3,7 +3,7 @@
Various blocks
-
+
Blockquotes
@@ -25,7 +25,7 @@
Blockquote second paragraph.
-
+
Admonitions
@@ -61,7 +61,7 @@
Warning second paragraph.
-
+
Blurb
@@ -69,7 +69,7 @@
Blurb
-
+
Inline
blocks
diff --git a/test/callouts.gold b/test/callouts.gold
index 403c7e0..f816ed0 100644
--- a/test/callouts.gold
+++ b/test/callouts.gold
@@ -12,13 +12,13 @@
int roll_die () {
- boost :: uniform_int <> dist ( 1 , 6 );
+ boost :: uniform_int <> dist ( 1 , 6 );
}
-
+
create a uniform_int distribution
@@ -30,13 +30,13 @@
int roll_die () {
- boost :: variate_generator < boost :: mt19937 &, boost :: uniform_int <> > die ( gen , dist );
+ boost :: variate_generator < boost :: mt19937 &, boost :: uniform_int <> > die ( gen , dist );
}
-
+
test
@@ -50,13 +50,13 @@
int roll_die () {
- boost :: variate_generator < boost :: mt19937 &, boost :: uniform_int <> > die ( gen , dist );
+ boost :: variate_generator < boost :: mt19937 &, boost :: uniform_int <> > die ( gen , dist );
}
-
+
test
@@ -70,13 +70,13 @@
int roll_die () {
- boost :: variate_generator < boost :: mt19937 &, boost :: uniform_int <> > die ( gen , dist );
+ boost :: variate_generator < boost :: mt19937 &, boost :: uniform_int <> > die ( gen , dist );
}
-
+
test
@@ -90,24 +90,24 @@
int roll_die () {
- boost :: variate_generator < boost :: mt19937 &, boost :: uniform_int <> > die ( gen , dist );
-boost :: uniform_int <> dist ( 1 , 6 );
+ boost :: variate_generator < boost :: mt19937 &, boost :: uniform_int <> > die ( gen , dist );
+boost :: uniform_int <> dist ( 1 , 6 );
}
-
+
callout 1
-
+
callout 2
-
+
create a uniform_int distribution
@@ -115,16 +115,16 @@
-boost :: uniform_int <> dist ( 1 , 6 );
+boost :: uniform_int <> dist ( 1 , 6 );
-
+
callout 2
-
+
create a uniform_int distribution
diff --git a/test/code-block.gold b/test/code-block.gold
index 7c65577..15b9214 100644
--- a/test/code-block.gold
+++ b/test/code-block.gold
@@ -26,7 +26,7 @@ Code block line 2.
Paragraph.
-
-
+
H4
-
+
H6
diff --git a/test/heading-1.5.gold b/test/heading-1.5.gold
index f8eeef5..e41fe5a 100644
--- a/test/heading-1.5.gold
+++ b/test/heading-1.5.gold
@@ -3,76 +3,76 @@
Heading Test 1.5
-
diff --git a/test/heading-1.6.gold b/test/heading-1.6.gold
index 0154eb3..217da62 100644
--- a/test/heading-1.6.gold
+++ b/test/heading-1.6.gold
@@ -3,99 +3,99 @@
Heading Test 1.6
-
diff --git a/test/identifier_1_5.gold b/test/identifier_1_5.gold
index 36dcfba..0255101 100644
--- a/test/identifier_1_5.gold
+++ b/test/identifier_1_5.gold
@@ -3,7 +3,7 @@
Identifiers in quickbook 1.5
-
+
Test
heading with code
diff --git a/test/identifier_1_6.gold b/test/identifier_1_6.gold
index b2f18a7..070e914 100644
--- a/test/identifier_1_6.gold
+++ b/test/identifier_1_6.gold
@@ -3,7 +3,7 @@
Identifiers in quickbook 1.6
-
+
Test
heading with code
diff --git a/test/include/code-include.gold b/test/include/code-include.gold
index d12dd39..07f37bc 100644
--- a/test/include/code-include.gold
+++ b/test/include/code-include.gold
@@ -141,28 +141,28 @@
// return 'em, foo man!
return "foo" ;
}
-std :: string foo_bar ()
+std :: string foo_bar ()
{
- return "foo-bar" ;
+ return "foo-bar" ;
}
class x
{
public :
- x () : n ( 0 )
+ x () : n ( 0 )
{
}
- ~ x ()
+ ~ x ()
{
}
- int get () const
+ int get () const
{
return n ;
}
- void set ( int n_ )
+ void set ( int n_ )
{
n = n_ ;
}
@@ -170,33 +170,33 @@
-
+
The Mythical FooBar. See Foobar
for details
-
+
return 'em, foo-bar man!
-
+
Constructor
-
+
Destructor
-
+
Get the n member variable
-
+
Set the n member variable
diff --git a/test/include/doc-title1-1.5.gold b/test/include/doc-title1-1.5.gold
index 61813ee..f2fb532 100644
--- a/test/include/doc-title1-1.5.gold
+++ b/test/include/doc-title1-1.5.gold
@@ -3,25 +3,25 @@
Doc Title 1
-
+
a1
-
+
inc1
-
+
a2
-
+
inc2
-
+
a3
-
+
inc3
-
+
a4
diff --git a/test/include/doc-title1a-1.5.gold b/test/include/doc-title1a-1.5.gold
index 30852b9..0ee226e 100644
--- a/test/include/doc-title1a-1.5.gold
+++ b/test/include/doc-title1a-1.5.gold
@@ -2,25 +2,25 @@
Doc Title 1a
-
+
a1
-
+
inc1
-
+
a2
-
+
inc2
-
+
a3
-
+
inc3
-
+
a4
diff --git a/test/include/include-id-1.5.gold b/test/include/include-id-1.5.gold
index 6246b52..4944d08 100644
--- a/test/include/include-id-1.5.gold
+++ b/test/include/include-id-1.5.gold
@@ -3,24 +3,24 @@
Include Id Test
-
+
Simple include
-
+
Simple include
-
+
Title, no id
-
+
Title, no id
-
+
Title
with id
-
- Title
+
+ Title
with id
diff --git a/test/include/include-id-1.6.gold b/test/include/include-id-1.6.gold
index 2ae30ad..1f4cb88 100644
--- a/test/include/include-id-1.6.gold
+++ b/test/include/include-id-1.6.gold
@@ -3,33 +3,33 @@
Include Id Test
-
+
Simple include
-
+
Simple include
Include without id
-
+
Title, no id
Include without id
-
+
Title, no id
Include with id
-
+
Title with id
Include with id
-
+
Title with id
diff --git a/test/quickbook-manual.gold b/test/quickbook-manual.gold
index 086219b..38a638e 100644
--- a/test/quickbook-manual.gold
+++ b/test/quickbook-manual.gold
@@ -15,7 +15,7 @@
2002 2004 2006 Joel de Guzman,
Eric Niebler
-
+
Distributed under 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 )
@@ -103,7 +103,7 @@
Change Log
-
+
Version
1.3
@@ -459,7 +459,7 @@ the true business precept.]
-