Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
contentblock.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "contentblock.h"
5
6#include <QJsonArray>
7#include <QStringList>
8
10
11using namespace Qt::Literals::StringLiterals;
12
13namespace IR {
14
15/*!
16 \enum IR::InlineType
17 \internal
18 \brief Discriminator for inline content elements within a block.
19
20 Inline types represent formatting and content that flows within a block
21 element (paragraph, heading, etc.). They can nest — for example, Bold
22 containing Text, or Link containing Code.
23
24 \value Text Plain text content.
25 \value Code Inline code span, such as a class or function name.
26 \value Link Hyperlink to another page or external resource.
27 \value Bold Bold-formatted text.
28 \value Italic Italic-formatted text.
29 \value Teletype Monospaced text, typically rendered as \c{<tt>}.
30 \value Underline Underlined text.
31 \value Strikethrough Struck-through text.
32 \value Subscript Subscript text.
33 \value Superscript Superscript text.
34 \value Parameter Function parameter name.
35 \value LineBreak Explicit line break within a block.
36 \value Image Inline image.
37 \value Keyword Index keyword anchor.
38 \value Target Named anchor target for cross-references.
39*/
40
41/*!
42 \enum IR::BlockType
43 \internal
44 \brief Discriminator for structural block elements in documentation.
45
46 Block types represent the structural elements of documentation content:
47 paragraphs, code blocks, lists, sections, and callout blocks. They nest
48 to form the document structure (e.g., List containing ListItems, each
49 containing Paragraphs).
50
51 \value Paragraph A paragraph of text with inline content.
52 \value CodeBlock A block of source code, optionally with a language attribute.
53 \value List An ordered or unordered list containing ListItem children.
54 \value ListItem A single item within a List.
55 \value Section A document section containing a heading and child blocks.
56 \value SectionHeading A section heading with a level attribute (1–6).
57 \value Note A note callout block.
58 \value Warning A warning callout block.
59 \value Important An important callout block.
60 \value Details A collapsible details block.
61 \value Brief The brief description of a documented entity.
62 \value Div A generic container block.
63 \value Quotation A block quotation.
64 \value Legalese A legal text block, such as a license notice.
65 \value HorizontalRule A horizontal separator rule.
66 \value Table A table container (reserved for future use).
67 \value TableRow A row within a table (reserved for future use).
68 \value TableCell A cell within a table row (reserved for future use).
69 \value Raw Raw format-specific content passed through without processing.
70*/
71
72/*!
73 \struct IR::InlineContent
74 \internal
75 \brief Represents inline content within a documentation block.
76
77 InlineContent is a format-agnostic representation of inline content
78 such as text, code, links, and formatting. Instances nest recursively
79 to represent formatting like bold text containing a link.
80
81 Each element is either a \e leaf (has \c text, no \c children) or a
82 \e container (has \c children, no \c text). This invariant is enforced
83 by Q_ASSERT in debug builds. Typically, content-bearing types such as
84 Text, Code, and Image are leaves, while formatting types such as Bold,
85 Italic, and Link are containers whose children carry the text.
86
87 The \c href and \c title fields are metadata that can be set on either
88 leaf or container elements (e.g., Link uses \c href with children;
89 Image uses \c href as a leaf).
90
91 This is a pure value type with no dependencies on QDoc's core
92 infrastructure. It belongs in QDocLib.
93
94 \sa ContentBlock, BlockType
95*/
96
97/*!
98 \struct IR::ContentBlock
99 \internal
100 \brief Represents a structural block element in documentation.
101
102 ContentBlock is a format-agnostic representation of documentation
103 structure. Each block is either a \e{leaf block} (has \c inlineContent,
104 no \c children) or a \e{container block} (has \c children, no
105 \c inlineContent). This invariant is enforced by Q_ASSERT in debug
106 builds. Typically, content-bearing blocks such as Paragraph, CodeBlock,
107 and SectionHeading are leaves, while structural blocks such as List,
108 Section, and callout blocks (Note, Warning, etc.) are containers.
109
110 The \c attributes field holds type-specific metadata as a QJsonObject.
111 Attribute keys use camelCase for compatibility with Inja dot notation
112 in templates (e.g., \c{block.attributes.listType}). Type IDs in the
113 \c type field use kebab-case (e.g., \c{"code-block"}).
114
115 This is a pure value type with no dependencies on QDoc's core
116 infrastructure. It belongs in QDocLib. Multiple renderers can read
117 the same ContentBlock concurrently — the frozen IR design supports
118 parallel rendering per output format.
119
120 \sa InlineContent, InlineType
121*/
122
123// Returns the kebab-case string ID for an InlineType.
125{
126 switch (type) {
127 case InlineType::Text: return u"text"_s;
128 case InlineType::Code: return u"code"_s;
129 case InlineType::Link: return u"link"_s;
130 case InlineType::Bold: return u"bold"_s;
131 case InlineType::Italic: return u"italic"_s;
132 case InlineType::Teletype: return u"teletype"_s;
133 case InlineType::Underline: return u"underline"_s;
134 case InlineType::Strikethrough: return u"strikethrough"_s;
135 case InlineType::Subscript: return u"subscript"_s;
136 case InlineType::Superscript: return u"superscript"_s;
137 case InlineType::Parameter: return u"parameter"_s;
138 case InlineType::LineBreak: return u"line-break"_s;
139 case InlineType::Image: return u"image"_s;
140 case InlineType::Keyword: return u"keyword"_s;
141 case InlineType::Target: return u"target"_s;
142 }
143 Q_UNREACHABLE();
144}
145
146// Returns the kebab-case string ID for a BlockType.
148{
149 switch (type) {
150 case BlockType::Paragraph: return u"paragraph"_s;
151 case BlockType::CodeBlock: return u"code-block"_s;
152 case BlockType::List: return u"list"_s;
153 case BlockType::ListItem: return u"list-item"_s;
154 case BlockType::Section: return u"section"_s;
155 case BlockType::SectionHeading: return u"section-heading"_s;
156 case BlockType::Note: return u"note"_s;
157 case BlockType::Warning: return u"warning"_s;
158 case BlockType::Important: return u"important"_s;
159 case BlockType::Details: return u"details"_s;
160 case BlockType::Brief: return u"brief"_s;
161 case BlockType::Div: return u"div"_s;
162 case BlockType::Quotation: return u"quotation"_s;
163 case BlockType::Legalese: return u"legalese"_s;
164 case BlockType::HorizontalRule: return u"horizontal-rule"_s;
165 case BlockType::Table: return u"table"_s;
166 case BlockType::TableRow: return u"table-row"_s;
167 case BlockType::TableCell: return u"table-cell"_s;
168 case BlockType::Raw: return u"raw"_s;
169 }
170 Q_UNREACHABLE();
171}
172
173/*!
174 Converts the InlineContent to a QJsonObject for template rendering.
175
176 The JSON uses kebab-case type IDs matching the convention in IR::Document
177 classification. Leaf elements (no children) include a \c text key with
178 their text content. Container elements (with children) omit \c text to
179 avoid redundancy — the text is available in their children.
180
181 Optional fields (\c href, \c title) are omitted when empty.
182 The \c children array is omitted when empty.
183*/
185{
186 Q_ASSERT(children.isEmpty() || text.isEmpty());
187
188 QJsonObject json;
189 json["type"_L1] = inlineTypeId(type);
190
191 if (children.isEmpty())
192 json["text"_L1] = plainText();
193
194 if (!href.isEmpty())
195 json["href"_L1] = href;
196 if (!title.isEmpty())
197 json["title"_L1] = title;
198
199 if (!children.isEmpty()) {
200 QJsonArray arr;
201 for (const auto &child : children)
202 arr.append(child.toJson());
203 json["children"_L1] = arr;
204 }
205
206 return json;
207}
208
209/*!
210 Returns the concatenated plain text of this inline element and all its
211 children, recursively.
212
213 For leaf elements (Text, Code, Keyword, Target, Parameter, Image),
214 returns the \c text field. For LineBreak, returns a newline character.
215 For container elements (Bold, Italic, Link, etc.), concatenates the
216 plain text of all children.
217*/
219{
220 Q_ASSERT(children.isEmpty() || text.isEmpty());
221 if (type == InlineType::LineBreak)
222 return u"\n"_s;
223
224 if (!children.isEmpty()) {
225 QStringList parts;
226 parts.reserve(children.size());
227 for (const auto &child : children)
228 parts.append(child.plainText());
229 return parts.join(u""_s);
230 }
231
232 return text;
233}
234
235/*!
236 Converts the ContentBlock to a QJsonObject for template rendering.
237
238 The JSON uses kebab-case type IDs. A computed \c text key contains the
239 concatenated plain text of all inline content or children. Empty
240 collections (\c inlines, \c children, \c attributes) are omitted.
241*/
243{
244 Q_ASSERT(inlineContent.isEmpty() || children.isEmpty());
245
246 QJsonObject json;
247 json["type"_L1] = blockTypeId(type);
248 json["text"_L1] = plainText();
249
250 if (!attributes.isEmpty())
251 json["attributes"_L1] = attributes;
252
253 if (!inlineContent.isEmpty()) {
254 QJsonArray arr;
255 for (const auto &inline_ : inlineContent)
256 arr.append(inline_.toJson());
257 json["inlines"_L1] = arr;
258 }
259
260 if (!children.isEmpty()) {
261 QJsonArray arr;
262 for (const auto &child : children)
263 arr.append(child.toJson());
264 json["children"_L1] = arr;
265 }
266
267 return json;
268}
269
270/*!
271 Returns the concatenated plain text of this block's inline content or
272 child blocks, recursively.
273
274 For leaf blocks with inline content (paragraphs, headings), concatenates
275 all inline text. For container blocks (lists, sections), concatenates
276 the plain text of child blocks separated by newlines.
277*/
279{
280 Q_ASSERT(inlineContent.isEmpty() || children.isEmpty());
281 if (!inlineContent.isEmpty()) {
282 QStringList parts;
283 parts.reserve(inlineContent.size());
284 for (const auto &inline_ : inlineContent)
285 parts.append(inline_.plainText());
286 return parts.join(u""_s);
287 }
288
289 if (!children.isEmpty()) {
290 QStringList parts;
291 parts.reserve(children.size());
292 for (const auto &child : children)
293 parts.append(child.plainText());
294 return parts.join(u"\n"_s);
295 }
296
297 return {};
298}
299
300} // namespace IR
301
302QT_END_NAMESPACE
Definition builder.cpp:14
static QString inlineTypeId(InlineType type)
static QString blockTypeId(BlockType type)
BlockType
InlineType
Combined button and popup list for selecting options.
Represents a structural block element in documentation.
QJsonObject toJson() const
Converts the ContentBlock to a QJsonObject for template rendering.
QString plainText() const
Returns the concatenated plain text of this block's inline content or child blocks,...
Represents inline content within a documentation block.
QJsonObject toJson() const
Converts the InlineContent to a QJsonObject for template rendering.
QString plainText() const
Returns the concatenated plain text of this inline element and all its children, recursively.