Skip to content

Commit bfa2d67

Browse files
committed
issue doxygen#8788 Quotes in inline code confuse Markdown parser
1 parent 853133e commit bfa2d67

File tree

8 files changed

+68
-7
lines changed

8 files changed

+68
-7
lines changed

doc/Doxyfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,4 @@ LATEX_EXTRA_STYLESHEET = manual.sty
7070
LATEX_EMOJI_DIRECTORY = ../doc
7171
WARN_AS_ERROR = FAIL_ON_WARNINGS
7272
HTML_PROJECT_COOKIE = doxygen_docs
73+
MARKDOWN_STRICT = NO

src/commentcnv.l

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,15 +783,15 @@ SLASHopt [/]*
783783
}
784784
<VerbatimCode>"''" {
785785
copyToOutput(yyscanner,yytext,yyleng);
786-
if (yyextra->blockName=="``") // support for ``text''
786+
if (!Config_getBool(MARKDOWN_STRICT) && yyextra->blockName=="``") // support for ``text''
787787
{
788788
yyextra->inVerbatim=false;
789789
BEGIN(yyextra->lastCommentContext);
790790
}
791791
}
792792
<VerbatimCode>"'" {
793793
copyToOutput(yyscanner,yytext,yyleng);
794-
if (yyextra->blockName=="`") // support for `text'
794+
if (!Config_getBool(MARKDOWN_STRICT) && yyextra->blockName=="`") // support for `text'
795795
{
796796
yyextra->inVerbatim=false;
797797
BEGIN(yyextra->lastCommentContext);

src/config.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,19 @@ Go to the <a href="commands.html">next</a> section or return to the
698698
The output of markdown processing is further processed by Doxygen, so you
699699
can mix Doxygen, HTML, and XML commands with Markdown formatting.
700700
Disable only in case of backward compatibilities issues.
701+
]]>
702+
</docs>
703+
</option>
704+
<option type='bool' id='MARKDOWN_STRICT' defval='1' depends='MARKDOWN_SUPPORT'>
705+
<docs>
706+
<![CDATA[
707+
If the \c MARKDOWN_STRICT tag is enabled then Doxygen treats text in comments as Markdown formatted
708+
also in cases where Doxygen's native markup format conflicts with that of Markdown. This is only relevant
709+
in cases where backticks are used. Doxygen's native markup style allows a single quote to end a
710+
text fragment started with a backtick and then treat it as a piece of quoted text, whereas in Markdown such text fragment
711+
is treated as verbatim and only ends when a second matching backtick is found. Also, Doxygen's native markup
712+
format requires double quotes to be escaped when they appear in a backtick section, whereas this is not needed
713+
for Markdown.
701714
]]>
702715
</docs>
703716
</option>

src/markdown.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,17 @@ static QCString escapeSpecialChars(const QCString &s)
248248
switch (c)
249249
{
250250
case '"':
251-
if (pc!='\\') { insideQuote=!insideQuote; }
251+
if (pc!='\\')
252+
{
253+
if (Config_getBool(MARKDOWN_STRICT))
254+
{
255+
result+='\\';
256+
}
257+
else // For Doxygen's markup style a quoted text is left untouched
258+
{
259+
insideQuote=!insideQuote;
260+
}
261+
}
252262
result+=c;
253263
break;
254264
case '<':
@@ -1641,6 +1651,7 @@ int Markdown::Private::processCodeSpan(std::string_view data,size_t offset)
16411651
/* finding the next delimiter with the same amount of backticks */
16421652
size_t i = 0;
16431653
char pc = '`';
1654+
bool markdownStrict = Config_getBool(MARKDOWN_STRICT);
16441655
for (end=nb; end<size; end++)
16451656
{
16461657
//AUTO_TRACE_ADD("c={} nb={} i={} size={}",data[end],nb,i,size);
@@ -1688,15 +1699,15 @@ int Markdown::Private::processCodeSpan(std::string_view data,size_t offset)
16881699
pc = '\n';
16891700
i = 0;
16901701
}
1691-
else if (data[end]=='\'' && nb==1 && (end+1==size || (end+1<size && data[end+1]!='\'' && !isIdChar(data[end+1]))))
1702+
else if (!markdownStrict && data[end]=='\'' && nb==1 && (end+1==size || (end+1<size && data[end+1]!='\'' && !isIdChar(data[end+1]))))
16921703
{ // look for quoted strings like 'some word', but skip strings like `it's cool`
16931704
out+="&lsquo;";
16941705
out+=data.substr(nb,end-nb);
16951706
out+="&rsquo;";
16961707
AUTO_TRACE_EXIT("quoted end={}",end+1);
16971708
return static_cast<int>(end+1);
16981709
}
1699-
else if (data[end]=='\'' && nb==2 && end+1<size && data[end+1]=='\'')
1710+
else if (!markdownStrict && data[end]=='\'' && nb==2 && end+1<size && data[end+1]=='\'')
17001711
{ // look for '' to match a ``
17011712
out+="&ldquo;";
17021713
out+=data.substr(nb,end-nb);

src/scanner.l

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7337,14 +7337,14 @@ NONLopt [^\n]*
73377337
}
73387338
}
73397339
<DocCopyBlock>"''"/[^a-z_A-Z0-9-] {
7340-
if (endVerbatimBlock(yyscanner,"``",2))
7340+
if (!Config_getBool(MARKDOWN_STRICT) && endVerbatimBlock(yyscanner,"``",2))
73417341
{
73427342
BEGIN(DocBlock);
73437343
}
73447344
yyextra->docBlock << yytext;
73457345
}
73467346
<DocCopyBlock>"'"/[^'a-z_A-Z0-9-] {
7347-
if (endVerbatimBlock(yyscanner,"`",1))
7347+
if (!Config_getBool(MARKDOWN_STRICT) && endVerbatimBlock(yyscanner,"`",1))
73487348
{
73497349
BEGIN(DocBlock);
73507350
}

testing/110_backticks.dox

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// objective: test various forms of backtick handling
2+
// config: MARKDOWN_STRICT = NO
23
// check: indexpage.xml
34
/** @mainpage
45
Text with `single` backtick.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US">
3+
<compounddef id="md_113__markdown__strict" kind="page">
4+
<compoundname>md_113__markdown__strict</compoundname>
5+
<title>113_markdown_strict</title>
6+
<briefdescription>
7+
</briefdescription>
8+
<detaileddescription>
9+
<para>Single quote inside backtick fragment should not end the verbatim section:</para>
10+
<para>Declare <computeroutput>x</computeroutput> like this <computeroutput>var x='c'</computeroutput>.</para>
11+
<para>Single quote inside double backtick fragment should not end the verbatim section:</para>
12+
<para>Declare <computeroutput>y</computeroutput> like this <computeroutput>var y='d'</computeroutput>.</para>
13+
<para>Double quotes characters do not need to be escaped in a verbatim fragment:</para>
14+
<para>Unescaped <computeroutput>"</computeroutput>quotes<computeroutput>"</computeroutput>. </para>
15+
</detaileddescription>
16+
<location file="113_markdown_strict.md"/>
17+
</compounddef>
18+
</doxygen>

testing/113_markdown_strict.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!--
2+
// objective: test markdown strict setting
3+
// config: MARKDOWN_STRICT = YES
4+
// check: md_113__markdown__strict.xml
5+
-->
6+
7+
Single quote inside backtick fragment should not end the verbatim section:
8+
9+
Declare `x` like this `var x='c'`.
10+
11+
Single quote inside double backtick fragment should not end the verbatim section:
12+
13+
Declare `y` like this ``var y='d'``.
14+
15+
Double quotes characters do not need to be escaped in a verbatim fragment:
16+
17+
Unescaped `"`quotes`"`.

0 commit comments

Comments
 (0)