11using namespace Qt::Literals::StringLiterals;
16 case Genus::CPP:
return u"cpp"_s;
17 case Genus::QML:
return u"qml"_s;
18 case Genus::DOC:
return u"doc"_s;
19 case Genus::API:
return u"api"_s;
20 case Genus::DontCare:
return {};
28
29
30
31
32
33
34
35
36
37
38
39
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
96
97
98
99
100
101
102
103
104
105
106
107
108
110 DiagnosticHandler diagnosticHandler)
111 : m_briefHandling(briefHandling), m_headingOffset(headingOffset),
136
137
138
139
140
141
142
143
148 m_inlinePath.clear();
149 m_inlineBaseDepths.clear();
156 processAtoms(firstAtom);
160 while (!m_blockPath.isEmpty())
162 m_inlinePath.clear();
163 m_inlineBaseDepths.clear();
171
172
173
174
175
180 atom = skipFormatIfBlock(atom);
187 atom = dispatchAtom(atom);
195
196
197
198
199
200
201
202
203
204
205
206
212 while (atom && depth > 0) {
223
224
225
226
231 if (m_briefHandling == BriefHandling::Include)
232 openBlock(BlockType::Paragraph);
247 openBlock(BlockType::Paragraph);
255 addLeafInline(InlineType::Text, atom->string());
259 addLeafInline(InlineType::Code, atom->string());
267 attrs[
"language"_L1] = u"qml"_s;
269 attrs[
"language"_L1] = u"cpp"_s;
270 attrs[
"bad"_L1] =
true;
271 }
else if (atom->count() >= 2 && !atom->string(1).isEmpty()) {
272 attrs[
"language"_L1] = atom->string(1);
274 attrs[
"language"_L1] = u"cpp"_s;
277 openBlock(BlockType::CodeBlock, attrs);
278 addLeafInline(InlineType::Text, atom->string());
292 link.href = atom->string();
294 link.children.append({
InlineType::Text, atom->string(), {}, {}, {}, {}, {} });
295 addInline(
std::move(link));
301 if (Q_UNLIKELY(m_blockPath.isEmpty()))
308 link.href = atom->string();
315 auto *mutableAtom =
const_cast<
Atom *>(atom);
317 QString genusStr = genusToString(genus);
318 if (!genusStr.isEmpty())
319 link.attributes[
"linkGenus"_L1] = genusStr;
320 if (Tree *domain = mutableAtom->domain())
321 link.attributes[
"linkModule"_L1] = domain->physicalModuleName();
324 pushInlineContainer(
std::move(link));
336 const QString &fmt = atom->string();
350 pushInlineContainer(
std::move(bold));
354 InlineType type = formattingToInlineType(fmt);
359 container
.type = type;
360 pushInlineContainer(
std::move(container));
365 const QString &fmt = atom->string();
369 const qsizetype base = m_inlineBaseDepths.isEmpty() ? 0 : m_inlineBaseDepths.last();
370 if (m_inlinePath.size() > base) {
372 m_inlinePath.removeLast();
384 const qsizetype base = m_inlineBaseDepths.isEmpty() ? 0 : m_inlineBaseDepths.last();
385 if (m_inlinePath.size() > base)
386 m_inlinePath.removeLast();
390 case Atom::SectionLeft:
391 openBlock(BlockType::Section);
400 attrs[
"level"_L1] = atom->string().toInt() + m_headingOffset;
401 openBlock(BlockType::SectionHeading, attrs);
411 const QString &listType = atom->string();
412 attrs[
"listType"_L1] = listType;
414 openBlock(BlockType::DefinitionList, attrs);
416 openBlock(BlockType::List, attrs);
426 if (parent->type == BlockType::DefinitionList)
427 openBlock(BlockType::DefinitionDescription);
429 openBlock(BlockType::ListItem);
442 openBlock(BlockType::Note);
449 case Atom::WarningLeft:
450 openBlock(BlockType::Warning);
458 addLeafInline(InlineType::LineBreak, {});
462 openBlock(BlockType::HorizontalRule);
468 attrs[
"annotatedList"_L1] = atom->string();
469 openBlock(BlockType::Div, attrs);
476 attrs[
"generatedList"_L1] = atom->string();
477 openBlock(BlockType::Div, attrs);
484 QString tableStyle = u"generic"_s;
487 for (
int i = 0; i < atom->count(); ++i) {
488 const QString &arg = atom->string(i);
489 if (arg ==
"borderless"_L1)
491 else if (arg.contains(
'%'_L1))
497 if (width ==
"%"_L1) {
499 int pct = atom->string(0).toInt(&ok);
500 width = ok ? QString::number(pct) +
'%'_L1 : QString();
503 attrs[
"style"_L1] = tableStyle;
504 if (!width.isEmpty())
505 attrs[
"width"_L1] = width;
506 openBlock(BlockType::Table, attrs);
514 case Atom::TableHeaderLeft:
515 openBlock(BlockType::TableHeaderRow);
522 case Atom::TableRowLeft:
523 openBlock(BlockType::TableRow);
532 const QString &spec = atom->string();
533 if (!spec.isEmpty()) {
534 const auto parts = QStringView{spec}.split(u',');
535 if (parts.size() >= 2) {
536 int colspan = qMax(1, parts[0].toInt());
537 int rowspan = qMax(1, parts[1].toInt());
539 attrs[
"colspan"_L1] = colspan;
541 attrs[
"rowspan"_L1] = rowspan;
544 openBlock(BlockType::TableCell, attrs);
552 case Atom::ListTagLeft:
553 openBlock(BlockType::DefinitionTerm);
562 attrs[
"class"_L1] = u"centerAlign"_s;
563 openBlock(BlockType::Paragraph, attrs);
567 img.href = atom->string();
570 addInline(
std::move(img));
580 if (Q_UNLIKELY(m_blockPath.isEmpty()))
585 img.href = atom->string();
588 addInline(
std::move(img));
613
614
615
616
617
618
623 block.attributes =
std::move(attrs);
625 m_inlineBaseDepths.append(m_inlinePath.size());
627 if (m_blockPath.isEmpty()) {
628 m_result.append(std::move(block));
629 m_blockPath.append(m_result.size() - 1);
631 auto *parent = resolveBlock();
632 parent->children.append(
std::move(block));
633 m_blockPath.append(parent->children.size() - 1);
638
639
640
641
642
643
644
647 if (!m_blockPath.isEmpty()) {
648 if (Q_UNLIKELY(m_inlineBaseDepths.isEmpty())) {
649 m_inlinePath.clear();
651 m_inlineBaseDepths.clear();
655 const qsizetype expectedDepth = m_inlineBaseDepths.last();
656 if (m_inLink && m_inlinePath.size() > expectedDepth)
658 m_inlinePath.resize(expectedDepth);
659 m_inlinePath.resize(expectedDepth);
660 m_inlineBaseDepths.removeLast();
661 m_blockPath.removeLast();
666
667
668
669
670
671
672
673
674
675
678 if (!m_inlinePath.isEmpty()) {
679 resolveInline()->children.append(
std::move(inline_));
680 }
else if (!m_blockPath.isEmpty()) {
681 resolveBlock()->inlineContent.append(
std::move(inline_));
684 m_diagnose(QtWarningMsg, u"Dropping inline content outside any block"_s);
689
690
691
697 addInline(
std::move(ic));
701
702
703
704
705
706
707
708
709
712 if (!m_inlinePath.isEmpty()) {
713 auto *parent = resolveInline();
714 parent->children.append(
std::move(container));
715 m_inlinePath.append(parent->children.size() - 1);
716 }
else if (!m_blockPath.isEmpty()) {
717 auto *block = resolveBlock();
718 block->inlineContent.append(
std::move(container));
719 m_inlinePath.append(block->inlineContent.size() - 1);
724
725
726
727
728
729
732 Q_ASSERT(!m_blockPath.isEmpty());
733 Q_ASSERT(m_blockPath[0] >= 0 && m_blockPath[0] < m_result.size());
735 for (qsizetype i = 1; i < m_blockPath.size(); ++i) {
736 Q_ASSERT(m_blockPath[i] >= 0 && m_blockPath[i] < block->children.size());
737 block = &block->children[m_blockPath[i]];
743
744
745
746
747
748
752 Q_ASSERT(!m_inlinePath.isEmpty());
753 Q_ASSERT(m_inlinePath[0] >= 0 && m_inlinePath[0] < block->inlineContent.size());
755 for (qsizetype i = 1; i < m_inlinePath.size(); ++i) {
756 Q_ASSERT(m_inlinePath[i] >= 0 && m_inlinePath[i] < ic->children.size());
757 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 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.