3

We need a specific JSF tag to be allowed in the RTF (this component is abstracted away from 'general editors' and is part of a more technical aspect).

Whilst we can update the TcmXHTML.config and this works for the tag that I need... however as this is a JSF tag I actually need < h:output >something< \h:output >

I've tried putting h:output into new-blocklevel-tags and tried with

output in new-inline-tags and h in the new-blocklevel-tags

Current contents of the tcmXhtml.config are:

numeric-entities: true
drop-empty-paras: true
drop-proprietary-attributes: false
break-before-br: true
word-2000: false
wrap: 0
tidy-mark: false
uppercase-tags: false
uppercase-attributes: false
output-xml:true
logical-emphasis: true
fix-backslash: false
char-encoding: utf8
input-encoding: utf8
output-encoding: utf8
fix-uri: true
indent-cdata: false
//indent: auto
new-blocklevel-tags: article aside canvas details figcaption figure footer header hgroup nav output progress section video h
new-inline-tags: audio datalist mark meter summary time output
new-empty-tags: command source track

Any suggestions on the format to get this permitted (short of creating the same holder as a plain text field)?

UPDATE

So this text+JSF tag+text is already what we (as Jaime and ThatITBloke suggest) already use as part of a resolved "merge field". As this is likely a one-off scenario the technical team wanted to avoid parsing another 'format' of string during the publish process and simply allow this syntax directly.

I think the main answer to the question is that this can't be done through the tcmxhtml configuration without specific 'work' so it's either a case of

  • support another content placeholder for this merge-field and use a plain text block or
  • support another format of 'snippet/merge-field'
2
  • The format may change but if the approach is the same, considering making the merge field-to-output configurable. That might be fields for Grep or an equivalent replace() method or even an XSLT file or TBB. Feb 14, 2015 at 19:45
  • The answer is 'no' it can't (and possible that it shouldn't be) - so Jaime had the best workaround - using specifically the TBB code from John. Thanks Feb 20, 2015 at 13:04

4 Answers 4

7

I am going to give it a shot...

What I would do is to use a different syntax for the tag in the RTF: instead of < h:output >something< \h:output > I would do something like { h:output } something { \h:output }. That would solve the problem of not-allowed tags in the RTF, since this syntax would be considered text.

Then if what you need is the original syntax (< h:output >something< \h:output >) you can have a TBB that parses the output and converts back from { h:output } something { \h:output } to < h:output >something< \h:output >.

And then when you publish you get your output with the right syntax, because I assume this output is only going to be "executed" in the front-end, right?

Moreover, your tag in the RTF is something that you would have to enter manually and you can tell your developers (I read that this is not an "editor's" field) to use the curly brackets instead of the < and > chars.

This would simplify the scenario.

3

If I've understood correctly, this is similar to an issue we had a few months ago and while changing the above file worked for most of what we wanted to add, there were a couple of tags that, like yours, still weren't being allowed.

As the TCMXHTML config is applied on component save, we decided to add some functionality to the ResolveXHTML function in the default template building block as this function is run on all RTF fields on publish. The code does a replace on certain codes entered into the RTF field to produce what we want. In our case it was enabling some special characters and resolving different domains depending on whether the page is published to one of our test environments or production. We have set up a series of replacements like so:

str = replace(str,"†","&#8224;")
str = replace(str,"%APPS%",appSecDomainPrefix)

We also have another function that uses a regular experession to change certain span tags entered by our content editors into JSP variables:

Function resolveTags(ByVal xhtml)
   Dim objRegExp
   Set objRegExp = New RegExp
   objRegExp.Pattern = "(<span class=""smarttag"">)([\w_]*)(</span>)"
   objRegExp.Global = True
   resolveTags = objRegExp.Replace(xhtml, "<%= $2 %>")
End Function

So when the content editors enter this:

<span class="smarttag">variableName</span>

What actually gets published is this:

<%= variableName %>

Something along those lines should help with what you need to do.

2
  • The class could be added to the CMS stylesheet (and even styled a certain way) so editors would first select an element in the rich text format area and then choose a style (e.g. smarttag). This would let them add the class without needing to edit the source. Feb 12, 2015 at 17:27
  • This is a really nice idea - one that I've used previous also Alvin - as we've allowed non-standard attributes it could also support other attributes/properties that the JSF tag may need over-time. In the pot for consideration also. Feb 13, 2015 at 12:27
3

Why not use a plain text field? You can store whatever you like in there. Rich text fields are designed to allow non-technical editors to inject content-with-markup into the website but as a developer you should not have any issues writing the correct HTML yourself.

2

If you go with Jamie's solution here's a TBB that you can use to perform the replace for you. You'd need to run this tbb after you've got the output produced into the package:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tridion.ContentManager.Templating;
using Tridion.ContentManager.Templating.Assembly;

namespace ContentBloom.Tridion.Templating.Core
{
    /// <summary>
    /// ResolveJSFTags = searches for the JSF tags in the content in the format {h:jsftag} and replaces
    /// them for their true tags, e.g "<h:jsptag>"
    /// </summary>
    class ResolveJSFTags : ITemplate
    {
        public void Transform(Engine engine, Package package)
        {
            // build up a list of the JSF tags
            List<string> jsfTags = new List<string>();

            // opening replace bracket
            string openingReplace = "{";
            // closing replace bracket
            string closingReplace = "}";

            jsfTags.Add("h:body");
            jsfTags.Add("h:button");
            jsfTags.Add("h:column");
            jsfTags.Add("h:commandButton");
            jsfTags.Add("h:commandLink");
            jsfTags.Add("h:dataTable");
            jsfTags.Add("h:form");
            jsfTags.Add("h:graphicImage");
            jsfTags.Add("h:head");
            jsfTags.Add("h:inputHidden");
            jsfTags.Add("h:inputSecret");
            jsfTags.Add("h:inputText");
            jsfTags.Add("h:inputTextarea");
            jsfTags.Add("h:link");
            jsfTags.Add("h:message");
            jsfTags.Add("h:messages");
            jsfTags.Add("h:outputFormat");
            jsfTags.Add("h:outputLabel");
            jsfTags.Add("h:output");
            jsfTags.Add("h:outputLink");
            jsfTags.Add("h:outputScript");
            jsfTags.Add("h:outputStylesheet");
            jsfTags.Add("h:outputText");
            jsfTags.Add("h:panelGrid");
            jsfTags.Add("h:panelGroup");
            jsfTags.Add("h:selectBooleanCheckbox");
            jsfTags.Add("h:selectManyCheckbox");
            jsfTags.Add("h:selectManyListbox");
            jsfTags.Add("h:selectManyMenu");
            jsfTags.Add("h:selectOneListbox");
            jsfTags.Add("h:selectOneMenu");
            jsfTags.Add("h:selectOneRadio");


            // get the output from the package
            string output = package.GetByName(Package.OutputName).GetAsString();

            // loop through my list and replace the {h:jsftag}
            foreach (string jsfTag in jsfTags)
            {
                output = output.Replace(openingReplace+jsfTag+closingReplace, "<"+jsfTag+">");
                output = output.Replace(openingReplace + "/" + jsfTag + closingReplace, "</" + jsfTag + ">");
            }

            // remove the original output from the package
            package.Remove(package.GetByName(Package.OutputName));

            // store the updated output into the package
            package.PushItem(Package.OutputName, package.CreateStringItem(ContentType.Html, output));
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.