Skip to content

Latest commit

 

History

History
269 lines (207 loc) · 9.72 KB

b-content.md

File metadata and controls

269 lines (207 loc) · 9.72 KB

<b:content>

Тег <b:content> определяет точку вставки контента, если для него явно не задана точка вставки. Имеется ввиду контент, который находится внутри <b:include> и не обрамлен специальными тегами вроде <b:append>, <b:replace> и т.д.

Принцип работы

Исходный шаблон:

<button class="button">
  {caption}
  <b:content/>
</button>

Модифицирующий шаблон:

<b:include src="./button.tmpl">
  My content
</b:include>

Результат:

<button class="button">
  {caption}
  <b:content>
    My content
  </b:content>
</button>

Здесь и далее в результате указывается <b:content>, хотя в реальной разметке (та что будет отдана браузеру) такого элемента нет. Это делается для того, чтобы показать где будет в результат определена точка вставки.

Механика

Весь контент внутри <b:include> не обрамленный в специальные теги вставляется на место <b:content>. Пример:

<button class="button">
  {caption}
  <b:content/>
</button>
<b:include src="./button.tmpl">
  foo
  <b:replace ref="caption">
    replaced
  </b:replace>
  bar
</b:include>

Результат:

<button class="button">
  replaced
  <b:content>
    foo
    bar
  </b:content>
</button>

Неявное определение <b:content>

В случае отсутствия <b:content> в подключаемом шаблоне, считается, что <b:content> указан в конце описания шаблона. Это повторяет поведение шаблонов до введения <b:content>. Например:

<button class="button">
  {caption}
</button>

Будет эквивалентно:

<button class="button">
  {caption}
</button>
<b:content/>

Такое определение является неявным и имеет меньший приоритет по отношению к явному определению <b:content>. (см. Наследование и крайние случаи)

Контент по умолчанию

Внутри <b:content> можно указывать любую разметку. Это содержимое будет оставаться до тех пор, пока содержимое шаблона не будет подключено через <b:include>, внутри которого есть не обрамленный в специальные теги (теги с префиксом b:) контент.

Пример шаблона кнопки:

<button class="button">
  <b:content>
    {caption}
  </b:content>
</button>

В таком случае, чтобы заменить содержимое новым, не нужно использовать <b:replace> или <b:remove>. Достаточно просто указать необходимое содержимое внутри <b:include> не обрамляя в специальные теги:

<b:include src="./button.tmpl">
  <img  /> My content
</b:include>

В результате получим:

<button class="button">
  <b:content>
    <img  /> My content
  </b:content>
</button>

Как видно, явный <b:content> сохранил свое местоположение, но его содержимое было заменено на новое.

Взаимодействие с операциями трансформации декларации

Содержимое <b:content> (дочерние токены) является такой же частью декларации как и все остальное. То есть оно доступно для любых операций с использованием ссылок. Операции <b:replace>, <b:remove>, <b:prepend>, <b:append> и все операции связанные с атрибутами работают без изменений. Операции <b:before> и <b:after> для токенов внутри <b:content> работают так, как будто <b:content> обычный элемент. То есть, если маркер-ссылка находится внутри <b:content>, то новый контент вставляется внутрь <b:content>, а не перед ним.

<button class="button">
  <b:content>
    {caption}
  </b:content>
</button>
<b:include src="./button.tmpl">
  <b:before ref="caption">
    My content
  </b:before>
</b:include>

Результат:

<button class="button">
  <b:content>
    My content{caption}
  </b:content>
</button>

Для <b:content> используется специальная ссылка - :content (то что имя начинается с двоеточия делает невозможным задать такую ссылку другим способом, то есть используя маркеры или атрибут b:ref).

<button class="button">
  <!-- <b:before ref=":content"/> -->
  <b:content>
    <!-- <b:prepend ref=":content"/> -->
    My content{caption}
    <!-- <b:append ref=":content"/> -->
  </b:content>
  <!-- <b:after ref=":content"/> -->
</button>

Стоить помнить, что если во включаемом шаблоне нет <b:content>, то операции трансформации будут производиться с неявным <b:content>, расположенным в конце декларации.

Операции по работе с атрибутами игнорируются (с варнингом), так как это виртуальный элемент не имеющий атрибутов. Инструкции <b:add-ref> и <b:remove-ref> не имееют силы и выбрасывают предупреждение.

Наследование и крайние случаи

Если есть несколько определений <b:include>, то выигрывает последнее определение по натуральному обходу дерева. Остальные определения игнорируются, то есть из декларации удаляется определение <b:content>, но его содержимое сохраняется. Простой случай:

<div>
  <b:content>  <!-- проигравший, тег будет удален, содержимое останется -->
    one
  </b:content>
  <b:content>  <!-- победитель, будет использоваться -->
    two
  </b:content>
</div>

Эквивалентно:

<div>
  one
  <b:content>
    two
  </b:content>
</div>

По той же логике, <b:content> вложенный в <b:content> так же выигрывает.

<div>
  <b:content>
    one
    <b:content>  <!-- победитель -->
      two
    </b:content>
  </b:content>
</div>

Результат:

<div>
  one
  <b:content>
    two
  </b:content>
</div>

Если есть хотя бы одно явное определение <b:content>, то игнорируются все неявные. При этом учитываются <b:content> не только в описании самого шаблона, но и в описании включаемых шаблонов.

Если включается несколько шаблонов, и нужно определить явно в какой из них должно попадать содержимое при наследовании, необходимо вставить <b:content> в нужный шаблон. Например, шаблон источник:

<div class="section">
  <b:content/>
</div>

Шаблон включающий несколько шаблонов, с явным указанием куда помещать содержимое:

<div class="layout">
  <b:include src="./section.tmpl">
    some content
    <b:content/>
  </b:include>

  <b:include src="./section.tmpl">
    some content
  </b:include>
</div>

В данном примере, если не указать явно <b:content> в первом <b:include>, то контент будет вставляться во второе включение.

Если в шаблоне нет явного <b:content> и нет явного во включаемых шаблонах, то будет использоваться неявный в самом шаблоне, который расположен в конце самого шаблона.