24std::string toGHLink(
const std::string &heading)
27 std::regex sanitizer{
"[^a-zA-Z0-9-]"};
28 std::regex spaces{
"\\s"};
35 [](
unsigned char c) { return std::tolower(c); });
36 return "#" + sanitized;
38 }
catch (
const std::regex_error &e) {
39 std::cerr <<
"Error sanitizing link: " << e.
what() <<
'\n';
47template <
typename ATTRIBUTE_T>
50 out <<
"<!ATTLIST " << ElementName <<
" " << attr.getName() <<
" CDATA ";
52 if (attr.hasDefaultValue()) {
53 out <<
"\"" << attr.getDefaultValue() <<
"\"";
63template <
typename ATTRIBUTE_T>
70 attr.getUserDocumentation());
72 if (attr.hasDefaultValue()) {
73 fmt::print(out,
" `{}` |", attr.getDefaultValue());
78 const auto &options = attr.getOptions();
79 if (options.empty()) {
82 fmt::print(out,
" `{}` |", fmt::join(options,
"`, `"));
88template <
typename ATTRIBUTE_T>
91 out << attr.getName() <<
"=\"";
92 if (attr.hasDefaultValue()) {
93 fmt::print(out,
"{}", attr.getDefaultValue());
102template <
typename ATTRIBUTE_T>
106 if (attr.hasValidation()) {
109 auto first = attr.getOptions().begin();
110 out <<
'\'' << *first <<
'\'';
113 for (; first != attr.getOptions().
end(); ++first) {
114 out <<
" or '" << *first <<
'\'';
118 if (attr.hasDefaultValue()) {
119 out <<
"(default:'" << attr.getDefaultValue() <<
"')";
130std::ostream &printDTD(std::ostream &out,
const XMLTag &tag,
bool start =
false)
133 out <<
"<!DOCTYPE " << tag.getFullName() <<
" [\n";
135 out <<
"<!ELEMENT " << tag.getFullName() <<
" ";
137 if (not tag.getSubtags().empty()) {
142 for (
auto const &subtag : tag.getSubtags()) {
144 std::string occurrenceChar;
149 occurrenceChar =
"*";
151 occurrenceChar =
"?";
153 occurrenceChar =
"+";
155 out << (first ?
"" :
", ") << subtag->getFullName() << occurrenceChar;
164 for (
const auto &attribute : tag.getAttributes()) {
165 std::visit([&out, &tag](
const auto &attribute) { printDTD(out, attribute, tag.getFullName()); }, attribute);
168 if (not tag.getSubtags().empty()) {
169 for (
const auto &subtag : tag.getSubtags()) {
170 printDTD(out, *subtag);
186std::ostream &printExample(std::ostream &out,
const XMLTag &tag,
int level)
188 std::string prefix(level * 2,
' ');
189 out << prefix <<
'<' << tag.getFullName();
190 for (
const auto &attribute : tag.getAttributes()) {
192 std::visit([&out](
const auto &attribute) { printExample(out, attribute); }, attribute);
194 if (tag.getSubtags().empty()) {
200 constexpr int threshold{1};
201 if (level >= threshold) {
202 out << std::string((level + 1) * 2,
' ') <<
"...\n";
204 std::set<std::string> namespaces;
205 for (
const auto &subtag : tag.getSubtags()) {
206 const auto ns = subtag->getNamespace();
208 if (namespaces.
count(subtag->getNamespace()) > 0) {
213 printExample(out, *subtag, level + 1) <<
'\n';
217 out << prefix <<
"</" << tag.getFullName() <<
'>';
227std::ostream &printMD(std::ostream &out,
const XMLTag &tag,
int level, std::map<std::string, int> &occurrences)
229 out << std::string(level,
'#') <<
' ' << tag.getFullName() <<
"\n\n";
231 out << tag.getDocumentation() <<
"\n\n";
233 out <<
"**Example:** \n```xml\n";
234 printExample(out, tag, 0) <<
"\n```\n\n";
236 if (
const auto &attributes = tag.getAttributes();
237 !attributes.empty()) {
238 out <<
"| Attribute | Type | Description | Default | Options |\n";
239 out <<
"| --- | --- | --- | --- | --- |\n";
241 for (
const auto &attribute : attributes) {
242 std::visit([&out](
const auto &attribute) { printMD(out, attribute) <<
'\n'; }, attribute);
247 if (not tag.getSubtags().empty()) {
248 out <<
"**Valid Subtags:**\n\n";
250 std::map<std::string, std::vector<std::string>> groupedTags;
252 for (
const auto &subtag : tag.getSubtags()) {
253 const auto heading = subtag->getFullName();
254 auto link = toGHLink(heading);
255 auto iter = occurrences.
find(heading);
256 if (iter != occurrences.
end()) {
260 occurrences.
emplace(heading, 1);
263 const auto ns = subtag->getNamespace();
265 fmt::print(out,
"* [{}]({}) `{}`\n",
268 subtag->getOccurrenceString(subtag->getOccurrence()));
270 auto &tags = groupedTags[ns];
271 tags.emplace_back(fmt::format(
"[{}]({}) `{}`",
274 subtag->getOccurrenceString(subtag->getOccurrence())));
277 for (
const auto &kv : groupedTags) {
278 out <<
"* " << kv.first <<
"\n";
279 for (
const auto &link : kv.second) {
280 out <<
" * " << link <<
"\n";
286 for (
const auto &subtag : tag.getSubtags()) {
287 printMD(out, *subtag, level + 1, occurrences) <<
'\n';
298std::ostream &printMD(std::ostream &out,
const XMLTag &tag,
int level = 1)
300 std::map<std::string, int> occurrences;
301 printMD(out, tag, level, occurrences);
306std::ostream &printDocumentation(std::ostream &out,
const XMLTag &tag,
int indentation)
308 const int linewidth = 1000;
310 for (
int i = 0; i < indentation; i++) {
314 out << indent <<
"<!-- TAG " << tag.getFullName() <<
'\n';
315 if (not tag.getDocumentation().empty()) {
316 std::string indentedDoc = indent +
" " + tag.getDocumentation();
322 for (
const auto &attribute : tag.getAttributes()) {
324 std::ostringstream attrDoc;
325 attrDoc << indent <<
" ATTR " <<
getName(attribute) <<
": "
326 <<
std::visit([](
const auto &attribute) {
return attribute.getUserDocumentation(); }, attribute);
331 std::ostringstream tagHead;
332 tagHead << indent <<
"<" << tag.getFullName();
335 for (
const std::string &namespaceName : tag.getNamespaces()) {
336 tagHead <<
" xmlns:" << namespaceName <<
"=\"precice." << namespaceName <<
"\"";
339 for (
const auto &attribute : tag.getAttributes()) {
340 tagHead << indent <<
" ";
341 std::visit([&tagHead](
const auto &attribute) { printDocumentation(tagHead, attribute); }, attribute);
346 if (not tag.getSubtags().empty()) {
348 for (
const auto &subtag : tag.getSubtags()) {
349 printDocumentation(out, *subtag, indentation + 3);
351 out << indent <<
"</" << tag.getFullName() <<
">\n\n";
372 printDocumentation(out, tag, 0);
Represents an XML tag to be configured automatically.
static std::string_view getOccurrenceString(Occurrence occurrence)
Occurrence
Types of occurrences of an XML tag.
std::string wrapText(const std::string &text, int linewidth, int indentation)
std::string getTypeName(const double &var)
contains the XML configuration parser.
void toMarkdown(std::ostream &out, const XMLTag &tag)
Prints the Markdown reference for the given tag.
void toDTD(std::ostream &out, const XMLTag &tag)
Prints the DTD reference for the given tag.
void toDocumentation(std::ostream &out, const XMLTag &tag)
Prints the XML reference for the given tag.
std::string getName(const XMLTag::Attribute &attribute)
Returns the name of an Attribute.
T regex_replace(T... args)