void syntax_highlight_actions::callout(parse_iterator, parse_iterator) { out << state.add_callout(qbk_value(state.current_file, marked_text.begin(), marked_text.end())); marked_text.clear(); }
std::string pre(quickbook::state& state, parse_iterator pos, value include_doc_id, bool nested_file) { // The doc_info in the file has been parsed. Here's what we'll do // *before* anything else. // // If there isn't a doc info block, then values will be empty, so most // of the following code won't actually do anything. value_consumer values = state.values.release(); // Skip over invalid attributes while (values.check(value::default_tag)) values.consume(); bool use_doc_info = false; std::string doc_type; value doc_title; if (values.check(doc_info_tags::type)) { doc_type = detail::to_s(values.consume(doc_info_tags::type).get_quickbook()); doc_title = values.consume(doc_info_tags::title); use_doc_info = !nested_file || qbk_version_n >= 106u; } else { if (!nested_file) { detail::outerr(state.current_file, pos.base()) << "No doc_info block." << std::endl; ++state.error_count; // Create a fake document info block in order to continue. doc_type = "article"; doc_title = qbk_value(state.current_file, pos.base(), pos.base(), doc_info_tags::type); use_doc_info = true; } } std::vector<std::string> duplicates; std::vector<value> escaped_attributes = consume_multiple_values(values, doc_info_tags::escaped_attribute); value qbk_version = consume_list(values, doc_attributes::qbk_version, &duplicates); value compatibility_mode = consume_list(values, doc_attributes::compatibility_mode, &duplicates); consume_multiple_values(values, doc_attributes::source_mode); value id = consume_value_in_list(values, doc_info_attributes::id, &duplicates); value dirname = consume_value_in_list(values, doc_info_attributes::dirname, &duplicates); value last_revision = consume_value_in_list(values, doc_info_attributes::last_revision, &duplicates); value purpose = consume_value_in_list(values, doc_info_attributes::purpose, &duplicates); std::vector<value> categories = consume_multiple_values(values, doc_info_attributes::category); value lang = consume_value_in_list(values, doc_info_attributes::lang, &duplicates); value version = consume_value_in_list(values, doc_info_attributes::version, &duplicates); std::vector<value> authors = consume_multiple_values(values, doc_info_attributes::authors); std::vector<value> copyrights = consume_multiple_values(values, doc_info_attributes::copyright); value license = consume_value_in_list(values, doc_info_attributes::license, &duplicates); std::vector<value> biblioids = consume_multiple_values(values, doc_info_attributes::biblioid); value xmlbase = consume_value_in_list(values, doc_info_attributes::xmlbase, &duplicates); values.finish(); if(!duplicates.empty()) { detail::outwarn(state.current_file->path) << (duplicates.size() > 1 ? "Duplicate attributes" : "Duplicate attribute") << ":" << boost::algorithm::join(duplicates, ", ") << "\n" ; } std::string include_doc_id_, id_; if (!include_doc_id.empty()) include_doc_id_ = detail::to_s(include_doc_id.get_quickbook()); if (!id.empty()) id_ = detail::to_s(id.get_quickbook()); // Quickbook version unsigned new_version = get_version(state, use_doc_info, qbk_version); if (new_version != qbk_version_n) { if (new_version >= 107u) { detail::outwarn(state.current_file->path) << "Quickbook " << (new_version / 100) << "." << (new_version % 100) << " is still under development and is " "likely to change in the future." << std::endl; } } if (new_version) { qbk_version_n = new_version; } else if (use_doc_info) { // hard code quickbook version to v1.1 qbk_version_n = 101; detail::outwarn(state.current_file, pos.base()) << "Quickbook version undefined. " "Version 1.1 is assumed" << std::endl; } state.current_file->version(qbk_version_n); // Compatibility Version unsigned compatibility_version = get_version(state, use_doc_info, compatibility_mode); if (!compatibility_version) { compatibility_version = use_doc_info ? qbk_version_n : state.document.compatibility_version(); } // Start file, finish here if not generating document info. if (!use_doc_info) { state.document.start_file(compatibility_version, include_doc_id_, id_, doc_title); return ""; } std::string id_placeholder = state.document.start_file_with_docinfo( compatibility_version, include_doc_id_, id_, doc_title); // Make sure we really did have a document info block. assert(doc_title.check() && !doc_type.empty()); // Set xmlbase std::string xmlbase_value; if (!xmlbase.empty()) { xinclude_path x = calculate_xinclude_path(xmlbase, state); if (!fs::is_directory(x.path)) { detail::outerr(xmlbase.get_file(), xmlbase.get_position()) << "xmlbase \"" << xmlbase.get_quickbook() << "\" isn't a directory." << std::endl; ++state.error_count; } else { xmlbase_value = x.uri; state.xinclude_base = x.path; } } // Warn about invalid fields if (doc_type != "library") { std::vector<std::string> invalid_attributes; if (!purpose.empty()) invalid_attributes.push_back("purpose"); if (!categories.empty()) invalid_attributes.push_back("category"); if (!dirname.empty()) invalid_attributes.push_back("dirname"); if(!invalid_attributes.empty()) { detail::outwarn(state.current_file->path) << (invalid_attributes.size() > 1 ? "Invalid attributes" : "Invalid attribute") << " for '" << doc_type << " document info': " << boost::algorithm::join(invalid_attributes, ", ") << "\n" ; } } // Write out header if (!nested_file) { state.out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" << "<!DOCTYPE " << doc_type << " PUBLIC \"-//Boost//DTD BoostBook XML V1.0//EN\"\n" << " \"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd\">\n" ; } state.out << '<' << doc_type << "\n" << " id=\"" << id_placeholder << "\"\n"; if(!lang.empty()) { state.out << " lang=\"" << doc_info_output(lang, 106) << "\"\n"; } if(doc_type == "library" && !doc_title.empty()) { state.out << " name=\"" << doc_info_output(doc_title, 106) << "\"\n"; } // Set defaults for dirname + last_revision if (!dirname.empty() || doc_type == "library") { state.out << " dirname=\""; if (!dirname.empty()) { state.out << doc_info_output(dirname, 106); } else if (!id_.empty()) { state.out << id_; } else if (!include_doc_id_.empty()) { state.out << include_doc_id_; } else if (!doc_title.empty()) { state.out << detail::make_identifier(doc_title.get_quickbook()); } else { state.out << "library"; } state.out << "\"\n"; } state.out << " last-revision=\""; if (!last_revision.empty()) { state.out << doc_info_output(last_revision, 106); } else { // default value for last-revision is now char strdate[64]; strftime( strdate, sizeof(strdate), (debug_mode ? "DEBUG MODE Date: %Y/%m/%d %H:%M:%S $" : "$" /* prevent CVS substitution */ "Date: %Y/%m/%d %H:%M:%S $"), current_gm_time ); state.out << strdate; } state.out << "\" \n"; if (!xmlbase.empty()) { state.out << " xml:base=\"" << xmlbase_value << "\"\n"; } state.out << " xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n"; std::ostringstream tmp; if(!authors.empty()) { tmp << " <authorgroup>\n"; BOOST_FOREACH(value_consumer author_values, authors) { while (author_values.check()) { value surname = author_values.consume(doc_info_tags::author_surname); value first = author_values.consume(doc_info_tags::author_first); tmp << " <author>\n" << " <firstname>" << doc_info_output(first, 106) << "</firstname>\n" << " <surname>" << doc_info_output(surname, 106) << "</surname>\n" << " </author>\n"; } } tmp << " </authorgroup>\n"; }