Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
.runTransformations
.#-----------------------------------------------------
.# A non-empty format after a macro must keep the macro inline without wrapping it in the format
.# (XRENDERING-766): see test1, test3 and test5. A format before a macro still wraps it (test5).
.# An *empty* format right after a macro (test2, test4) carries no content: the format is dropped and the
.# macro is emitted as a standalone block, exactly as if the format were not there. The dropped format must
.# not leak into the following block either - test2 is followed by "Padding", which must stay unformatted.
.# The xwiki/2.0 input therefore does not round-trip (the empty formats disappear), so input and output are
.# specified separately.
.#-----------------------------------------------------
.input|xwiki/2.0
.#-----------------------------------------------------
{{testsimpleinlinemacro/}}(% id="test1" %)hi

{{testsimpleinlinemacro/}}(% id="test2" %)

Padding

{{testsimpleinlinemacro/}}(% id="test3" %){{testsimpleinlinemacro/}}

{{testsimpleinlinemacro/}}(% id="test4" %)

(% id="test5" %){{testsimpleinlinemacro/}}
.#-----------------------------------------------------
.expect|event/1.0
.#-----------------------------------------------------
beginDocument
beginParagraph
beginMacroMarkerInline [testsimpleinlinemacro] []
onWord [simpleinlinemacro2]
endMacroMarkerInline [testsimpleinlinemacro] []
beginFormat [NONE] [[id]=[test1]]
onWord [hi]
endFormat [NONE] [[id]=[test1]]
endParagraph
beginMacroMarkerStandalone [testsimpleinlinemacro] []
beginParagraph
onWord [simpleinlinemacro3]
endParagraph
endMacroMarkerStandalone [testsimpleinlinemacro] []
beginParagraph
onWord [Padding]
endParagraph
beginParagraph
beginMacroMarkerInline [testsimpleinlinemacro] []
onWord [simpleinlinemacro4]
endMacroMarkerInline [testsimpleinlinemacro] []
beginFormat [NONE] [[id]=[test3]]
beginMacroMarkerInline [testsimpleinlinemacro] []
onWord [simpleinlinemacro5]
endMacroMarkerInline [testsimpleinlinemacro] []
endFormat [NONE] [[id]=[test3]]
endParagraph
beginMacroMarkerStandalone [testsimpleinlinemacro] []
beginParagraph
onWord [simpleinlinemacro6]
endParagraph
endMacroMarkerStandalone [testsimpleinlinemacro] []
beginParagraph
beginFormat [NONE] [[id]=[test5]]
beginMacroMarkerInline [testsimpleinlinemacro] []
onWord [simpleinlinemacro7]
endMacroMarkerInline [testsimpleinlinemacro] []
endFormat [NONE] [[id]=[test5]]
endParagraph
endDocument
.#-----------------------------------------------------
.expect|xwiki/2.0
.#-----------------------------------------------------
{{testsimpleinlinemacro/}}(% id="test1" %)hi

{{testsimpleinlinemacro/}}

Padding

{{testsimpleinlinemacro/}}(% id="test3" %){{testsimpleinlinemacro/}}

{{testsimpleinlinemacro/}}

(% id="test5" %){{testsimpleinlinemacro/}}
.#-----------------------------------------------------
.expect|annotatedxhtml/1.0
.#-----------------------------------------------------
<p><!--startmacro:testsimpleinlinemacro|-|-->simpleinlinemacro2<!--stopmacro--><span id="test1">hi</span></p><!--startmacro:testsimpleinlinemacro|-|--><p>simpleinlinemacro3</p><!--stopmacro--><p>Padding</p><p><!--startmacro:testsimpleinlinemacro|-|-->simpleinlinemacro4<!--stopmacro--><span id="test3"><!--startmacro:testsimpleinlinemacro|-|-->simpleinlinemacro5<!--stopmacro--></span></p><!--startmacro:testsimpleinlinemacro|-|--><p>simpleinlinemacro6</p><!--stopmacro--><p><span id="test5"><!--startmacro:testsimpleinlinemacro|-|-->simpleinlinemacro7<!--stopmacro--></span></p>
.#-----------------------------------------------------
.input|xhtml/1.0
.#-----------------------------------------------------
<p><!--startmacro:testsimpleinlinemacro|-|-->simpleinlinemacro2<!--stopmacro--><span id="test1">hi</span></p><!--startmacro:testsimpleinlinemacro|-|--><p>simpleinlinemacro3</p><!--stopmacro--><p>Padding</p><p><!--startmacro:testsimpleinlinemacro|-|-->simpleinlinemacro4<!--stopmacro--><span id="test3"><!--startmacro:testsimpleinlinemacro|-|-->simpleinlinemacro5<!--stopmacro--></span></p><!--startmacro:testsimpleinlinemacro|-|--><p>simpleinlinemacro6</p><!--stopmacro--><p><span id="test5"><!--startmacro:testsimpleinlinemacro|-|-->simpleinlinemacro7<!--stopmacro--></span></p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.#-----------------------------------------------------
.inputexpect|xwiki/2.1
.# Stored XWiki syntax of an inline macro (here a mention) followed by CKEditor's "xwiki-macro-inline-enforcer".
.# CKEditor appends this span (holding a non-breaking space) after an inline macro so the rendering round-trip of
.# the macro content keeps the macro inline instead of turning it into a block; CKEditor removes the span again
.# afterwards. The macro must therefore be emitted *before* the enforcer format and must never be wrapped inside
.# it - otherwise removing the enforcer span would delete the macro too (XWIKI-21973 / XRENDERING-766).
.# NOTE: the input line below ends with a space (the enforcer content); it is preserved as the format content so the
.# enforcer format is non-empty.
.#-----------------------------------------------------
{{mention reference="XWiki.Admin" style="FULL_NAME" anchor="XWiki-Admin-7qc"/}}(% id="xwiki-macro-inline-enforcer" %)
.#-----------------------------------------------------
.expect|event/1.0
.#-----------------------------------------------------
beginDocument
beginParagraph
onMacroInline [mention] [reference=XWiki.Admin|style=FULL_NAME|anchor=XWiki-Admin-7qc]
beginFormat [NONE] [[id]=[xwiki-macro-inline-enforcer]]
onSpace
endFormat [NONE] [[id]=[xwiki-macro-inline-enforcer]]
endParagraph
endDocument
.#-----------------------------------------------------
.expect|annotatedxhtml/1.0
.#-----------------------------------------------------
<p><!--startmacro:mention|-|reference="XWiki.Admin" style="FULL_NAME" anchor="XWiki-Admin-7qc"--><!--stopmacro--><span id="xwiki-macro-inline-enforcer">&nbsp;</span></p>
.#-----------------------------------------------------
.input|xhtml/1.0
.#-----------------------------------------------------
<p><!--startmacro:mention|-|reference="XWiki.Admin" style="FULL_NAME" anchor="XWiki-Admin-7qc"--><!--stopmacro--><span id="xwiki-macro-inline-enforcer">&nbsp;</span></p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.#---------------------------------------------------------------------------------------------------------
.# An empty format (parameters only) at the very end of a paragraph is currently dropped. Unlike a format right
.# after a still-pending macro or verbatim element (see XRENDERING-766), plain inline content followed by a trailing
.# empty parameter format does not preserve that format.
.#---------------------------------------------------------------------------------------------------------
.input|xwiki/2.0
.#---------------------------------------------------------------------------------------------------------
Paragraph1(% id="test" %)

Paragraph2

Paragraph3(% id="test" %)(%%)

Paragraph4
.#---------------------------------------------------------------------------------------------------------
.expect|event/1.0
.#---------------------------------------------------------------------------------------------------------
beginDocument
beginParagraph
onWord [Paragraph1]
endParagraph
beginParagraph
onWord [Paragraph2]
endParagraph
beginParagraph
onWord [Paragraph3]
endParagraph
beginParagraph
onWord [Paragraph4]
endParagraph
endDocument
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
.#---------------------------------------------------------------------------------------------------------
.# A non-empty format after verbatim text must keep the verbatim inline without wrapping it in the format
.# (XRENDERING-766). A format before verbatim still wraps it. An *empty* format right after verbatim carries
.# no content: the format is dropped and the verbatim is emitted as a standalone block, exactly as if the
.# format were not there. The dropped format must not leak into the following block either - the fourth case
.# is followed by "Padding", which must stay unformatted. The xwiki/2.0 input therefore does not round-trip
.# (the empty format disappears), so input and output are specified separately.
.#---------------------------------------------------------------------------------------------------------
.input|xwiki/2.0
.#---------------------------------------------------------------------------------------------------------
{{{verbatim}}}(% id="test" %)hi

(% id="test" %){{{verbatim}}}hi

(% id="test" %){{{verbatim}}}

{{{verbatim}}}(% id="test" %)

Padding

{{{verbatim1}}}(% id="test" %){{{verbatim2}}}
.#---------------------------------------------------------------------------------------------------------
.expect|event/1.0
.#---------------------------------------------------------------------------------------------------------
beginDocument
beginParagraph
onVerbatim [verbatim] [true]
beginFormat [NONE] [[id]=[test]]
onWord [hi]
endFormat [NONE] [[id]=[test]]
endParagraph
beginParagraph
beginFormat [NONE] [[id]=[test]]
onVerbatim [verbatim] [true]
onWord [hi]
endFormat [NONE] [[id]=[test]]
endParagraph
beginParagraph
beginFormat [NONE] [[id]=[test]]
onVerbatim [verbatim] [true]
endFormat [NONE] [[id]=[test]]
endParagraph
onVerbatim [verbatim] [false]
beginParagraph
onWord [Padding]
endParagraph
beginParagraph
onVerbatim [verbatim1] [true]
beginFormat [NONE] [[id]=[test]]
onVerbatim [verbatim2] [true]
endFormat [NONE] [[id]=[test]]
endParagraph
endDocument
.#---------------------------------------------------------------------------------------------------------
.expect|xwiki/2.0
.#---------------------------------------------------------------------------------------------------------
{{{verbatim}}}(% id="test" %)hi

(% id="test" %){{{verbatim}}}hi

(% id="test" %){{{verbatim}}}

{{{verbatim}}}

Padding

{{{verbatim1}}}(% id="test" %){{{verbatim2}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.#-----------------------------------------------------
.input|xhtml/1.0
.# An inline macro followed by the CKEditor "xwiki-macro-inline-enforcer" span (a parameter format holding a
.# non-breaking space, used to keep the macro inline) must round-trip with the macro *before* the span and never
.# wrapped inside it. If the macro were wrapped, CKEditor's removal of the enforcer span would delete the macro too
.# (XWIKI-21973 / XRENDERING-766).
.#-----------------------------------------------------
<p><!--startmacro:mention|-|reference="XWiki.Admin" style="FULL_NAME" anchor="XWiki-Admin-7qcxlk"--><!--stopmacro--><span id="xwiki-macro-inline-enforcer">&nbsp;</span></p>
.#-----------------------------------------------------
.expect|annotatedxhtml/1.0
.#-----------------------------------------------------
<p><!--startmacro:mention|-|reference="XWiki.Admin" style="FULL_NAME" anchor="XWiki-Admin-7qcxlk"--><!--stopmacro--><span id="xwiki-macro-inline-enforcer">&nbsp;</span></p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.#-----------------------------------------------------
.input|xhtml/1.0
.# An inline macro followed by CKEditor's "xwiki-macro-inline-enforcer" span must be parsed as an inline macro that
.# is *not* wrapped in the enforcer format: the onMacroInline event comes before beginFormat, not inside it. If the
.# macro were wrapped, CKEditor's removal of the enforcer span would delete the macro too (XWIKI-21973 /
.# XRENDERING-766). The enforcer span carries a non-breaking space, which is why it keeps the macro inline.
.#-----------------------------------------------------
<p><!--startmacro:mention|-|reference="XWiki.Admin" style="FULL_NAME" anchor="XWiki-Admin-7qcxlk"--><!--stopmacro--><span id="xwiki-macro-inline-enforcer">&nbsp;</span></p>
.#-----------------------------------------------------
.expect|event/1.0
.#-----------------------------------------------------
beginDocument
beginParagraph
onMacroInline [mention] [reference=XWiki.Admin|style=FULL_NAME|anchor=XWiki-Admin-7qcxlk]
beginFormat [NONE] [[id]=[xwiki-macro-inline-enforcer]]
onSpace
endFormat [NONE] [[id]=[xwiki-macro-inline-enforcer]]
endParagraph
endDocument
Original file line number Diff line number Diff line change
Expand Up @@ -599,9 +599,12 @@ protected void checkStyleOpened()
fMacroName = macroName;
fVerbatimContent = verbatimContent;
}
openFormat();
// First check if we encountered a verbatim or macro that we can now process as inline.
// Then open whatever format we encountered. If the format was before the verbatim or macro, we would have
// immediately recognized both as inline and processed them already.
checkVerbatim(true);
checkMacro(true);
openFormat();
}

private void checkTableCell()
Expand All @@ -627,6 +630,17 @@ private void checkVerbatim(boolean inline)

public void closeBlock()
{
// A format that trails a still-pending macro or verbatim element has no content: the element is emitted as
// a standalone block below, and the empty format is dropped here so it does not leak into the next block.
// The macro/verbatim condition is required: it excludes the checkStyleOpened() -> beginParagraph() ->
// closeBlock() re-entrant call (which temporarily clears these fields), where the pending format must be
// preserved so that it can wrap the following inline content.
if ((fMacroName != null || fVerbatimContent != null) && isNoBlockElements()
&& !WikiFormat.EMPTY.equals(fNewFormat))
{
fNewFormat = WikiFormat.EMPTY;
}

checkVerbatim(false);
checkMacro(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,44 @@ void testMacro() throws WikiParserException
"<pre class='wikimodel-macro' macroName='macro' param1='val1' param2='val2'><![CDATA[foo]]></pre>");
}

/**
* A macro at the start of a line followed by a format must be inline, and the format must not wrap the macro,
* see <a href="https://jira.xwiki.org/browse/XRENDERING-766">XRENDERING-766</a>.
*/
@Test
void testMacroFollowedByFormat() throws WikiParserException
{
// The format must not wrap the macro, only the content after it.
test("{{macro/}}(% id='test' %)hi",
"<p><span class='wikimodel-macro' macroName='macro'/>"
+ "<span class='wikimodel-parameters'[id='test']>hi</span></p>");

// A format before the macro wraps the macro, though.
test("(% id='test' %){{macro/}}",
"<p><span class='wikimodel-parameters'[id='test']>"
+ "<span class='wikimodel-macro' macroName='macro'/></span></p>");

// A trailing format with no content is dropped, and the macro becomes a standalone block (as if the
// empty format were not there).
test("{{macro/}}(% id='test' %)",
"<pre class='wikimodel-macro' macroName='macro'/>");

// The dropped empty format must not leak into the following paragraph.
test("{{macro/}}(% id='test' %)\n\nPadding",
"<pre class='wikimodel-macro' macroName='macro'/>\n"
+ "<p>Padding</p>");

// Only the second macro must be wrapped in the format.
test("{{macro/}}(% id='test' %){{macro/}}",
"<p><span class='wikimodel-macro' macroName='macro'/><span class='wikimodel-parameters'[id='test']>"
+ "<span class='wikimodel-macro' macroName='macro'/></span></p>");

// The same applies to verbatim content: an empty trailing format is dropped and the verbatim becomes
// a standalone block.
test("{{{verbatim}}}(% id='test' %)",
"<pre>verbatim</pre>");
}

@Test
void testMacroParameterEscaping() throws WikiParserException
{
Expand Down