Use .cshtml pages in Composite C1 that aren't strict XHTML - c1-cms

I need to include some .cshtml / razor pages in a Composite C1 site that do not enforce strict XHTML / XML.
ie - any unclosed tags at the moment, for example, prevent the page loading.
A client requires this; is it possible?
Thanks

Wrap bad / unsafe markup in a CDATA section. Since the strict XML requirement is primarily needed inside the Composite C1 render engine and is typically not a concern for browsers, Composite C1 treat CDATA sections as "messy markup" which it will not parse, but just emit raw:
<div>
<![CDATA[
Bad & ugly HTML!<br>
]]>
</div>
It will pass through Composite C1 unhindered and come out as:
<div>
Bad & ugly HTML!<br>
</div>
Above is quoted from http://docs.composite.net/Layout/Writing-XHTML
Here is a simple example with Razor syntax:
<div>
<![CDATA[
#{
string unstructuredMarkup = "Bad & ugly HTML!<br>";
#Html.Raw(unstructuredMarkup);
}
]]>
</div>

You can set the ReturnType of your function to string (the default is XhtmlDocument). You do this by overriding the ReturnType property like this
#functions
{
protected override Type FunctionReturnType
{
get { return typeof(string); }
}
}

Related

How to add attributes to elements with HtmlPurifier?

I'm looking to purify HTML with the HtmlPurifier package and add attributes to certain elements. Specifically, I'd like to add classes to <div> and <p> elements so that this:
<div>
<p>
Hello
</p>
</div>
Gets purified/transformed into this:
<div class="div-class">
<p class="p-class">
Hello
</p>
</div>
How would one go about doing this with HtmlPurifier? Is it possible?
I believe you could do this by doing something along these lines (though please treat this as pseudocode, the last time this scenario worked for me was years ago):
class HTMLPurifier_AttrTransform_DivClass extends HTMLPurifier_AttrTransform
{
public function transform($attr, $config, $context) {
$attr['class'] = 'div-class';
return $attr;
}
}
class HTMLPurifier_AttrTransform_ParaClass extends HTMLPurifier_AttrTransform
{
public function transform($attr, $config, $context) {
$attr['class'] = 'p-class';
return $attr;
}
}
$htmlDef = $this->configuration->getHTMLDefinition(true);
$div = $htmlDef->addBlankElement('div');
$div->attr_transform_post[] = new HTMLPurifier_AttrTransform_DivClass();
$para = $htmlDef->addBlankElement('p');
$para->attr_transform_post[] = new HTMLPurifier_AttrTransform_ParaClass();
Remember to allowlist the class attribute for div and p as well, if you haven't already.
That said, at first glance, HTML Purifier doesn't seem to be the right place for this kind of logic, since adding class names isn't relevant for the security of your site (or is it?). If you're already using HTML Purifier to allowlist your HTML tags, attributes and values, and just want to leverage its HTML-parsing capabilities for some light-weight additional DOM manipulation, I see no particular reason not to. :) But it might be worth reflecting on whether you want to add the classes using some other process (e.g. in the frontend, if that's relevant for your use case).

How can I do string interpolation in a string variable in React?

I have a variable coming from a static JSON file:
`const label = json.myString`
Where json.myString is "Hello, ${ name }". Since this is a variable, I do not know what it would be before hand.
And I want to do some string interpolation in my react component:
<div>{ label }</div>
How can I do this? Bonus points for a backup/default option if xyz is undefined
You should use template engine for this, for example, Mustache.
However, you can use an eval, but you don't want to use it, because it is unsafe in your case (some injections can be performed, if someone will perform a MITM-attack for your server, for example).
var a = "kappa"
console.log(eval("`Hello, ${a}!`"))
The other option that you can use is regular expressions.
There are 2 moments, that you should notice in this case:
Variables must be exist in some context, e.g. this, to allow stringified variables names be passed as key
You should not use special symbols of your template bounds inside template, or you should additionaly handle each special symbol inside regular expression.
var template = "My awesome template says: \"${ say }\""
var data = { say: "Hello!" }
console.log(template.replace(/\$\{([^}]+)\}/g, (match, group) => {
return data[group.trim()]
}))
By the way, this question is not React-specific, I suppose, but JS-specific. React doen't provide any profit features for this kind of logic tasks :)
The purpose of template literals is to avoid the usage of "some string" + "another string", and not much functionally.
In this scenario, it would be best to decouple the name with Hello.
That way, you could call
<div>Hello, ${name} </div>
In case you'd like to create a flexible greeting as well, you could then add the greeting as another string. E.g.:
{
name: "John Doe",
greeting: "Hello"
}
And go,
<div>${greeting}, ${name}</div>

Wagtail draftail paragraph style

I'm looking to add a custom BlockFeature to the wagtail draftail editor that converts to a paragraph tag with a specific class.
<p>A normal paragraph</p>
<p class="margin-0">A special paragraph using my custom feature</p>
This is my attempt:
#hooks.register('register_rich_text_features')
def register_margin0_feature(features):
"""
Registering the `margin-0` feature, which uses the `blockquote` Draft.js block type,
and is stored as HTML with a `<p class="margin-0">` tag.
"""
feature_name = 'margin-0'
type_ = 'custom'
tag = 'p'
classname = "margin-0"
control = {
'type': type_,
'label': '❝',
'description': 'Paragraph with margin-0',
# Optionally, we can tell Draftail what element to use when displaying those blocks in the editor.
'element': 'blockquote',
}
features.register_editor_plugin(
'draftail', feature_name, draftail_features.BlockFeature(control)
)
features.register_converter_rule('contentstate', feature_name, {
'from_database_format': {'p[margin-0]': BlockElementHandler(type_)},
'to_database_format': {
'block_map': {
type_: {
'element': tag,
'props': {
'class': 'margin-0',
},
},
},
},
})
This saves correctly to the database and generates the correct page markup, however, when I open the page in wagtail admin the draftail editor mistakes it for a normal paragraph.
Looking through the wagtail source I noticed this in html_ruleset.py:
Look for a rule matching an HTML element with the given name and attribute dict, and return the corresponding result object. If no rule matches, return None.
If multiple rules match, the one chosen is undetermined.
Since there is a built in 'p' tag handler, does this make recognising 'p class="margin-0"' impossible?
It would be great to be able to just write the custom class you want on each paragraph in the editor.
Yes, unfortunately the ruleset system doesn't currently give precedence to more specific rules, so there's no way to define a rule that supersedes the default <p> rule. This is an open feature request: https://github.com/wagtail/wagtail/pull/4527
However, note that the selector p[margin-0] is incorrect, as this would match a <p> element with a margin-0 attribute rather than a class attribute - it should be p[class="margin-0"].

Programmatically include xhtml fragment in MyFaces

I know it is possible in MyFaces to programmatically add a xhtml fragment to the component tree, instead of using ui:include.
The snipplet I am talking about is as (in the original form):
ViewDeclarationLanguage vdl = facesContext.getApplication().getViewHandler().getViewDeclarationLanguage(facesContext, facesContext.getViewRoot().getViewId());
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put("src", "/fragmentToInclude.xhtml");
UIComponent component = vdl.createComponent(facesContext, "http://java.sun.com/jsf/facelets", "include", attributes);
The problem I am facing is I am not able to pass in parameters, that would normally be passed in via <ui:param .../> tag.
What I tried, of course, was to add params into attributes map:
attributes.put("testingParam1", "Yeah, it worked!");
But this seems not to help. Content of my testing fragment is quite simple:
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<div class="testingDiv">#{empty testingParam1 ? 'testingParam1 IS EMPTY' : testingParam1}</div>
</ui:composition>
The fragment is properly loaded, but I only get that 'is empty' message.
I have walked through multiple resources but haven't found answer there:
NullPointerException in MyFaces facelet inclusion
http://lu4242.blogspot.cz/2014/01/whats-new-in-myfaces-22.html
https://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2014-03/message/12
https://java.net/projects/javaserverfaces-spec-public/lists/users/archive/2014-10/message/120
Please, do you know, is this even possible? Or am I missing something? Thanks for any hints.

Inserting image into visualforce email template (without hard-coding IDs)

The "official" solution for including images in visualforce email templates suggests hard coding IDs in your template to reference an image file stored as a document.
https://help.salesforce.com/HTViewHelpDoc?id=email_template_images.htm&language=en_US
Is there a better way that avoids hard coding instance ID and OID? I tried using the partner URL to grab the instance ID, but I got the following error
Error Error: The reference to entity "oid" must end with the ';' delimiter.
Using:
{!LEFT($Api.Partner_Server_URL_140,FIND(".com/",$Api.Partner_Server_URL_140)+3)/
to replace "https://na2.salesforce.com/"
in
"na2.salesforce.com/servlet/servlet.ImageServer?id=01540000000RVOe&oid=00Dxxxxxxxxx&lastMod=1233217920"
Should I use a static resource instead?
I've arrived here looking for an answer for this question related to hardcoded ID and OID in Visualforce e-mail templates. Well, I found a workaround for that.
First I needed to create a Visualforce Component:
<apex:component access="global" controller="LogomarcaController">
<apex:image url="{!LogoUrl}" />
</apex:component>
In the respective controller class, I've created a SFInstance property to get the correct URL Salesforce Instance, LogoUrl property to concatenate SFInstance and IDs... And Finally I've used Custom Settings (Config_Gerais__c.getInstance().ID_Documento_Logomarca__c) to configurate the ID of Image (in my case, Document Object) on Sandbox or Production:
public class LogomarcaController {
public String LogoUrl {
get {
id orgId = UserInfo.getOrganizationId();
String idDocumentoLogomarca = Config_Gerais__c.getInstance().ID_Documento_Logomarca__c;
return this.SfInstance + '/servlet/servlet.ImageServer?id=' + idDocumentoLogomarca + '&oid=' + orgId ;
}
}
public String SfInstance
{
get{
string SFInstance = URL.getSalesforceBaseUrl().toExternalForm();
list<string> Dividido = SFInstance.split('.visual', 0);//retira o restante a partir de .visual
SFInstance = dividido[0];
dividido = SFInstance.split('://',0);//retira o https://
SFInstance = dividido[1];
if(!SFInstance.contains('sybf')) //managed package prefix, if you need
{
SFInstance = 'sybf.'+ SFInstance;
}
return 'https://'+SFInstance;
}
}
}
And finally, I've added the component in Visualforce template:
<messaging:emailTemplate subject="Novo Ofício - {!relatedTo.name}" recipientType="User" relatedToType="Oficio__c" >
<messaging:htmlEmailBody >
<c:Logomarca />
</messaging:htmlEmailBody>
<messaging:plainTextEmailBody >
</messaging:plainTextEmailBody>
</messaging:emailTemplate>
PS: Some of my variables, properties and comments are in my native language (portuguese). If you have some problems understanding them, please ask me!
We ran into a similar problem and after trying various solutions, the following worked for us. In our case the image is uploaded as a content asset(https://help.salesforce.com/articleView?id=000320130&type=1&language=en_US&mode=1)
Solution:
<img src="{!LEFT($Api.Partner_Server_URL_260,FIND('/services',$Api.Partner_Server_URL_260))}/file-asset-public/<Image_Name_Here>?oid={!$Organization.Id}&height=50&width=50"/>

Resources