}
}
- if (isset($array['#markup']) && !$this->formatWhitespace) {
+ if (isset($array['#markup']) && (!$this->formatWhitespace || strpos($array['#markup'], '<') === FALSE)) {
$buf .= '>' . $array['#markup'] . '</' . $tag . '>';
}
elseif (isset($array['#markup'])) {
}
$doc = new DOMDocument();
+ $doc->preserveWhiteSpace = !$this->formatWhitespace;
@$doc->loadHTML("<html><body>$html</body></html>");
// FIXME: Validate expected number of child nodes
$arr[$attribute->name] = $this->decodeAttrValue($type, $txt);
}
if ($node->childNodes->length > 0) {
- // In shallow mode, return "af-markup" containers as-is
- if (!$this->deepCoding && !empty($arr['class']) && strpos($arr['class'], 'af-markup') !== FALSE) {
+ // In shallow mode, return markup as-is if node isn't supported by the gui editor
+ if (!$this->deepCoding && !$this->isNodeEditable($arr)) {
$arr['#markup'] = '';
foreach ($node->childNodes as $child) {
$arr['#markup'] .= $child->ownerDocument->saveXML($child);
}
}
+ /**
+ * Determine if a node is recognized by the gui editor.
+ *
+ * @param array $item
+ * @return bool
+ */
+ public function isNodeEditable(array $item) {
+ if ($item['#tag'] === 'af-field' || $item['#tag'] === 'af-form' || isset($item['af-fieldset'])) {
+ return TRUE;
+ }
+ $editableClasses = ['af-block', 'af-text', 'af-button'];
+ $classes = explode(' ', $item['class'] ?? '');
+ return (bool) array_intersect($editableClasses, $classes);
+ }
+
}
use \Civi\Test\Api3TestTrait;
use \Civi\Test\ContactTestTrait;
+ /**
+ * DOMDocument outputs some tags a little different than they were input.
+ * It's not really a problem but can trip up tests.
+ *
+ * @param array|string $markup
+ * @return array|string
+ */
+ private function fudgeMarkup($markup) {
+ if (is_array($markup)) {
+ foreach ($markup as $idx => $item) {
+ $markup[$idx] = $this->fudgeMarkup($item);
+ }
+ return $markup;
+ }
+ else {
+ return str_replace([' />', '/>'], ['/>', ' />'], $markup);
+ }
+ }
+
public function getBasicDirectives() {
return [
['mockPage', ['title' => '', 'description' => '', 'server_route' => 'civicrm/mock-page']],
->setLayoutFormat($readFormat)
->execute();
- $this->assertEquals($readLayout, $result[0]['layout'], "Based on \"$exampleName\", writing content as \"$updateFormat\" and reading back as \"$readFormat\".");
+ $this->assertEquals($readLayout, $this->fudgeMarkup($result[0]['layout']), "Based on \"$exampleName\", writing content as \"$updateFormat\" and reading back as \"$readFormat\".");
Civi\Api4\Afform::revert()->addWhere('name', '=', $formName)->execute();
}
->execute()
->first();
- $this->assertEquals($example['stripped'] ?? $example['shallow'], $result['layout']);
+ $this->assertEquals($example['stripped'] ?? $example['shallow'], $this->fudgeMarkup($result['layout']));
Civi\Api4\Afform::save()
->addRecord(['name' => $directiveName, 'layout' => $result['layout']])
->execute()
->first();
- $this->assertEquals($example['pretty'], $result['layout']);
+ $this->assertEquals($example['pretty'], $this->fudgeMarkup($result['layout']));
}
public function testAutoRequires() {
'html' => '<strong>New text!</strong>',
'pretty' => "<strong>New text!</strong>\n",
'shallow' => [
- ['#tag' => 'strong', '#children' => [['#text' => 'New text!']]],
+ ['#tag' => 'strong', '#markup' => 'New text!'],
],
'deep' => [
['#tag' => 'strong', '#children' => [['#text' => 'New text!']]],
<?php
return [
- 'html' => '<div><strong> New text!</strong><af-field name="do_not_sms" defn="{label: \'Do not do any of the emailing\'}" /></div>',
- 'pretty' => '<div>
- <strong>New text!</strong>
+ 'html' => '<div class="af-block"><strong> New text!</strong><strong class="af-text"> No whitespace! </strong><af-field name="do_not_sms" defn="{label: \'Do not do any of the emailing\'}" /></div>',
+ 'pretty' => '<div class="af-block">
+ <strong> New text!</strong>
+ <strong class="af-text">No whitespace!</strong>
<af-field name="do_not_sms" defn="{label: \'Do not do any of the emailing\'}" />
</div>
',
'stripped' => [
[
'#tag' => 'div',
+ 'class' => 'af-block',
'#children' => [
- ['#tag' => 'strong', '#children' => [['#text' => 'New text!']]],
+ ['#tag' => 'strong', '#markup' => ' New text!'],
+ ['#tag' => 'strong', 'class' => 'af-text', '#children' => [['#text' => 'No whitespace!']]],
['#tag' => 'af-field', 'name' => 'do_not_sms', 'defn' => "{label: 'Do not do any of the emailing'}"],
],
],
'shallow' => [
[
'#tag' => 'div',
+ 'class' => 'af-block',
'#children' => [
- ['#tag' => 'strong', '#children' => [['#text' => ' New text!']]],
+ ['#tag' => 'strong', '#markup' => ' New text!'],
+ ['#tag' => 'strong', 'class' => 'af-text', '#children' => [['#text' => ' No whitespace! ']]],
['#tag' => 'af-field', 'name' => 'do_not_sms', 'defn' => "{label: 'Do not do any of the emailing'}"],
],
],
'deep' => [
[
'#tag' => 'div',
+ 'class' => 'af-block',
'#children' => [
['#tag' => 'strong', '#children' => [['#text' => ' New text!']]],
+ ['#tag' => 'strong', 'class' => 'af-text', '#children' => [['#text' => ' No whitespace! ']]],
['#tag' => 'af-field', 'name' => 'do_not_sms', 'defn' => ['label' => 'Do not do any of the emailing']],
],
],
<?php
return [
- 'html' => '<span>First</span> <span>Second</span>',
- 'pretty' => "<span>First</span>\n<span>Second</span>\n",
- 'shallow' => [
- ['#tag' => 'span', '#children' => [['#text' => 'First']]],
- ['#text' => ' '],
- ['#tag' => 'span', '#children' => [['#text' => 'Second']]],
- ],
+ 'html' => '<span>First</span> <span>Second</span>',
+ 'pretty' => "<span>First</span>
+<span>Second</span>\n",
'stripped' => [
- ['#tag' => 'span', '#children' => [['#text' => 'First']]],
- ['#tag' => 'span', '#children' => [['#text' => 'Second']]],
+ ['#tag' => 'span', '#markup' => 'First'],
+ ['#tag' => 'span', '#markup' => 'Second'],
+ ],
+ 'shallow' => [
+ ['#tag' => 'span', '#markup' => 'First'],
+ ['#text' => ' '],
+ ['#tag' => 'span', '#markup' => 'Second'],
],
'deep' => [
['#tag' => 'span', '#children' => [['#text' => 'First']]],
- ['#text' => ' '],
+ ['#text' => ' '],
['#tag' => 'span', '#children' => [['#text' => 'Second']]],
],
];
'shallow' => [
[
'#tag' => 'div',
- '#children' => [
- ['#text' => 'One'],
- ['#comment' => ' uno '],
- ['#text' => ' Two '],
- ['#comment' => 'dos & so on '],
- ['#text' => ' Three'],
- ],
+ '#markup' => 'One<!-- uno --> Two <!--dos & so on --> Three',
],
['#comment' => 'tres-a--b---c'],
],
'pretty' => '<span class="one"></span>
<img class="two" />
<div>
- <br class="three" />
- <br />
+ <br class="three" /><br />
</div>
',
'shallow' => [
['#tag' => 'span', 'class' => 'one'],
['#tag' => 'img', 'class' => 'two'],
- [
- '#tag' => 'div',
- '#children' => [
- ['#tag' => 'br', 'class' => 'three'],
- ['#tag' => 'br'],
- ],
- ],
+ ['#tag' => 'div', '#markup' => '<br class="three" /><br />'],
],
'deep' => [
['#tag' => 'span', 'class' => 'one'],
return [
'html' => '<p><strong>Stylized</strong> text is <em>wonky</em> text!</p>',
- 'pretty' => "<p><strong>Stylized</strong> text is <em>wonky</em> text!</p>\n",
+ 'pretty' => "<p>
+ <strong>Stylized</strong> text is <em>wonky</em> text!
+</p>\n",
'shallow' => [
- ['#tag' => 'p', '#children' => [
- ['#tag' => 'strong', '#children' => [['#text' => 'Stylized']]],
- ['#text' => ' text is '],
- ['#tag' => 'em', '#children' => [['#text' => 'wonky']]],
- ['#text' => ' text!'],
- ]],
+ ['#tag' => 'p', '#markup' => '<strong>Stylized</strong> text is <em>wonky</em> text!'],
],
'deep' => [
- ['#tag' => 'p', '#children' => [
- ['#tag' => 'strong', '#children' => [['#text' => 'Stylized']]],
- ['#text' => ' text is '],
- ['#tag' => 'em', '#children' => [['#text' => 'wonky']]],
- ['#text' => ' text!'],
- ]],
+ [
+ '#tag' => 'p',
+ '#children' => [
+ ['#tag' => 'strong', '#children' => [['#text' => 'Stylized']]],
+ ['#text' => ' text is '],
+ ['#tag' => 'em', '#children' => [['#text' => 'wonky']]],
+ ['#text' => ' text!'],
+ ],
+ ],
],
];