11using namespace Qt::Literals::StringLiterals;
15 static const QRegularExpression tag(u"</?@[^>]*>"_s);
16 QString t = markedCode;
17 t.replace(tag, QString());
18 t.replace(u"""_s, u"\""_s);
19 t.replace(u">"_s, u">"_s);
20 t.replace(u"<"_s, u"<"_s);
21 t.replace(u"&"_s, u"&"_s);
28 case Genus::CPP:
return u"cpp"_s;
29 case Genus::QML:
return u"qml"_s;
30 case Genus::DOC:
return u"doc"_s;
31 case Genus::API:
return u"api"_s;
32 case Genus::DontCare:
return {};
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
108
109
110
111
112
113
114
115
116
117
118
119
120
122 DiagnosticHandler diagnosticHandler)
123 : m_briefHandling(briefHandling), m_headingOffset(headingOffset),
148
149
150
151
152
153
154
155
160 m_inlinePath.clear();
161 m_inlineBaseDepths.clear();
168 processAtoms(firstAtom);
172 while (!m_blockPath.isEmpty())
174 m_inlinePath.clear();
175 m_inlineBaseDepths.clear();
183
184
185
186
187
192 atom = skipFormatIfBlock(atom);
199 atom = dispatchAtom(atom);
207
208
209
210
211
212
213
214
215
216
217
218
224 while (atom && depth > 0) {
235
236
237
238
243 if (m_briefHandling == BriefHandling::Include)
244 openBlock(BlockType::Paragraph);
259 openBlock(BlockType::Paragraph);
267 addLeafInline(InlineType::Text, atom->string());
271 addLeafInline(InlineType::Code, stripCodeMarkerTags(atom->string()));
279 attrs[
"language"_L1] = u"qml"_s;
281 attrs[
"language"_L1] = u"cpp"_s;
282 attrs[
"bad"_L1] =
true;
283 }
else if (atom->count() >= 2 && !atom->string(1).isEmpty()) {
284 attrs[
"language"_L1] = atom->string(1);
286 attrs[
"language"_L1] = u"cpp"_s;
289 openBlock(BlockType::CodeBlock, attrs);
290 addLeafInline(InlineType::Text, stripCodeMarkerTags(atom->string()));
304 link.href = atom->string();
306 link.children.append({
InlineType::Text, atom->string(), {}, {}, {}, {}, {} });
307 addInline(
std::move(link));
313 if (m_blockPath.isEmpty())
314 openBlock(BlockType::Paragraph);
320 link.href = atom->string();
327 auto *mutableAtom =
const_cast<
Atom *>(atom);
329 QString genusStr = genusToString(genus);
330 if (!genusStr.isEmpty())
331 link.attributes[
"linkGenus"_L1] = genusStr;
332 if (Tree *domain = mutableAtom->domain())
333 link.attributes[
"linkModule"_L1] = domain->physicalModuleName();
336 pushInlineContainer(
std::move(link));
348 const QString &fmt = atom->string();
362 pushInlineContainer(
std::move(bold));
366 InlineType type = formattingToInlineType(fmt);
371 container
.type = type;
372 pushInlineContainer(
std::move(container));
377 const QString &fmt = atom->string();
381 const qsizetype base = m_inlineBaseDepths.isEmpty() ? 0 : m_inlineBaseDepths.last();
382 if (m_inlinePath.size() > base) {
384 m_inlinePath.removeLast();
396 const qsizetype base = m_inlineBaseDepths.isEmpty() ? 0 : m_inlineBaseDepths.last();
397 if (m_inlinePath.size() > base)
398 m_inlinePath.removeLast();
402 case Atom::SectionLeft:
403 openBlock(BlockType::Section);
412 attrs[
"level"_L1] = atom->string().toInt() + m_headingOffset;
413 openBlock(BlockType::SectionHeading, attrs);
423 const QString &listType = atom->string();
424 attrs[
"listType"_L1] = listType;
426 openBlock(BlockType::DefinitionList, attrs);
428 openBlock(BlockType::List, attrs);
438 if (parent->type == BlockType::DefinitionList)
439 openBlock(BlockType::DefinitionDescription);
441 openBlock(BlockType::ListItem);
454 openBlock(BlockType::Note);
461 case Atom::WarningLeft:
462 openBlock(BlockType::Warning);
470 addLeafInline(InlineType::LineBreak, {});
474 openBlock(BlockType::HorizontalRule);
480 attrs[
"annotatedList"_L1] = atom->string();
481 openBlock(BlockType::Div, attrs);
488 attrs[
"generatedList"_L1] = atom->string();
489 openBlock(BlockType::Div, attrs);
496 QString tableStyle = u"generic"_s;
499 for (
int i = 0; i < atom->count(); ++i) {
500 const QString &arg = atom->string(i);
501 if (arg ==
"borderless"_L1)
503 else if (arg.contains(
'%'_L1))
509 if (width ==
"%"_L1) {
511 int pct = atom->string(0).toInt(&ok);
512 width = ok ? QString::number(pct) +
'%'_L1 : QString();
515 attrs[
"style"_L1] = tableStyle;
516 if (!width.isEmpty())
517 attrs[
"width"_L1] = width;
518 openBlock(BlockType::Table, attrs);
526 case Atom::TableHeaderLeft:
527 openBlock(BlockType::TableHeaderRow);
534 case Atom::TableRowLeft:
535 openBlock(BlockType::TableRow);
544 const QString &spec = atom->string();
545 if (!spec.isEmpty()) {
546 const auto parts = QStringView{spec}.split(u',');
547 if (parts.size() >= 2) {
548 int colspan = qMax(1, parts[0].toInt());
549 int rowspan = qMax(1, parts[1].toInt());
551 attrs[
"colspan"_L1] = colspan;
553 attrs[
"rowspan"_L1] = rowspan;
556 openBlock(BlockType::TableCell, attrs);
564 case Atom::ListTagLeft:
565 openBlock(BlockType::DefinitionTerm);
574 attrs[
"class"_L1] = u"centerAlign"_s;
575 openBlock(BlockType::Paragraph, attrs);
579 img.href = atom->string();
582 addInline(
std::move(img));
592 if (Q_UNLIKELY(m_blockPath.isEmpty()))
597 img.href = atom->string();
600 addInline(
std::move(img));
625
626
627
628
629
630
635 block.attributes =
std::move(attrs);
637 m_inlineBaseDepths.append(m_inlinePath.size());
639 if (m_blockPath.isEmpty()) {
640 m_result.append(std::move(block));
641 m_blockPath.append(m_result.size() - 1);
643 auto *parent = resolveBlock();
644 parent->children.append(
std::move(block));
645 m_blockPath.append(parent->children.size() - 1);
650
651
652
653
654
655
656
659 if (!m_blockPath.isEmpty()) {
660 if (Q_UNLIKELY(m_inlineBaseDepths.isEmpty())) {
661 m_inlinePath.clear();
663 m_inlineBaseDepths.clear();
667 const qsizetype expectedDepth = m_inlineBaseDepths.last();
668 if (m_inLink && m_inlinePath.size() > expectedDepth)
670 m_inlinePath.resize(expectedDepth);
671 m_inlinePath.resize(expectedDepth);
672 m_inlineBaseDepths.removeLast();
673 m_blockPath.removeLast();
678
679
680
681
682
683
684
685
686
687
690 if (!m_inlinePath.isEmpty()) {
691 resolveInline()->children.append(
std::move(inline_));
692 }
else if (!m_blockPath.isEmpty()) {
693 resolveBlock()->inlineContent.append(
std::move(inline_));
696 m_diagnose(QtWarningMsg, u"Dropping inline content outside any block"_s);
701
702
703
709 addInline(
std::move(ic));
713
714
715
716
717
718
719
720
721
724 if (!m_inlinePath.isEmpty()) {
725 auto *parent = resolveInline();
726 parent->children.append(
std::move(container));
727 m_inlinePath.append(parent->children.size() - 1);
728 }
else if (!m_blockPath.isEmpty()) {
729 auto *block = resolveBlock();
730 block->inlineContent.append(
std::move(container));
731 m_inlinePath.append(block->inlineContent.size() - 1);
736
737
738
739
740
741
744 Q_ASSERT(!m_blockPath.isEmpty());
745 Q_ASSERT(m_blockPath[0] >= 0 && m_blockPath[0] < m_result.size());
747 for (qsizetype i = 1; i < m_blockPath.size(); ++i) {
748 Q_ASSERT(m_blockPath[i] >= 0 && m_blockPath[i] < block->children.size());
749 block = &block->children[m_blockPath[i]];
755
756
757
758
759
760
764 Q_ASSERT(!m_inlinePath.isEmpty());
765 Q_ASSERT(m_inlinePath[0] >= 0 && m_inlinePath[0] < block->inlineContent.size());
767 for (qsizetype i = 1; i < m_inlinePath.size(); ++i) {
768 Q_ASSERT(m_inlinePath[i] >= 0 && m_inlinePath[i] < ic->children.size());
769 ic = &ic->children[m_inlinePath[i]];
#define ATOM_FORMATTING_TELETYPE
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_FORMATTING_NOTRANSLATE
#define ATOM_FORMATTING_SUBSCRIPT
#define ATOM_FORMATTING_BOLD
#define ATOM_FORMATTING_TRADEMARK
#define ATOM_FORMATTING_ITALIC
#define ATOM_FORMATTING_LINK
#define ATOM_FORMATTING_SUPERSCRIPT
#define ATOM_FORMATTING_INDEX
#define ATOM_FORMATTING_UICONTROL
#define ATOM_FORMATTING_PARAMETER
The Atom class is the fundamental unit for representing documents internally.
AtomType type() const
Return the type of this atom.
virtual bool isLinkAtom() const
const Atom * next() const
Return the next atom in the atom list.
Converts Atom chains to QList<IR::ContentBlock> trees.
QList< ContentBlock > build(const Atom *firstAtom)
Walks the atom chain starting at firstAtom and returns a list of ContentBlock trees representing the ...
ContentBuilder(BriefHandling briefHandling=BriefHandling::Skip, int headingOffset=0, DiagnosticHandler diagnosticHandler={})
Constructs a ContentBuilder.
static QString genusToString(Genus genus)
static QString stripCodeMarkerTags(const QString &markedCode)
static InlineType formattingToInlineType(const QString &formatting)
Combined button and popup list for selecting options.
Represents a structural block element in documentation.
Represents inline content within a documentation block.