Write Tridion dreamweaver identifier as output package - tridion

While working on compound page templating project I have discovered very interesting issue. Customer uses ${stringvalue-session-or-something-specific} in their custom developed applications that are saved and rendered in component templates using XSLT. When try to render the component presentations containing reserved Tridion dreamweaver identifier (${}) I have got Template Builder error similar to
JScriptException: Expression '""["scopedTarget.personalia"]."" != ""' had error 'Expected identifier'
at Tridion.ContentManager.Templating.Expression.JScriptEvaluator.EvaluateToObject(String statement)
at Tridion.ContentManager.Templating.Expression.JScriptEvaluator.EvaluateToString(String statement)
Removing and replacing this identifiers is not solution acceptable by customer.
I was wondering what can be the best solution to cope this issue? Either using C# code to rendering component presentations, maybe create some custom rewrites( if it is possible because I got error from component presentations).

A similar thing happens if customers use JSP EL in their applications, which use the same ${...} syntax, and want to encapsulate this in their templates.
The most common solution is to replace this syntax with something like $[...] in the Dreamweaver templates and use a .Net TBB after the Dreamweaver template which uses string replacement or regular expressions to convert it.
See my gist for an example TBB that does this.

I normally use this code to "enable JSTL in templates". Since you can't change Tridion to use a different code identifier, you need to change your markup. Run this TBB at the END of your template to convert $[expression] to ${expression}
using System;
using System.Text.RegularExpressions;
using Tridion.ContentManager.Templating;
using Tridion.ContentManager.Templating.Assembly;
namespace TridionTemplates
{
[TcmTemplateTitle("Enable JSTL")]
public class EnableJSTL : ITemplate
{
private static readonly Regex JstlRegex = new Regex(#"\$\[.*\]");
public void Transform(Engine engine, Package package)
{
Item outputItem = package.GetByName(Package.OutputName);
string outputText = outputItem.GetAsString();
Match match = JstlRegex.Match(outputText);
while (match.Success)
{
String replaceJstl = match.Value.Replace("[", "{");
replaceJstl = replaceJstl.Replace("]", "}");
outputText = outputText.Replace(match.Value, replaceJstl);
match = match.NextMatch();
}
outputItem.SetAsString(outputText);
package.Remove(outputItem);
package.PushItem(Package.OutputName, outputItem);
}
}
}

If you absolutely can't change the syntax in your Dreamweaver templates (As I stated, I'm not sure I fully understand/agree with the reasons for that) then perhaps you could switch to using the Razor Mediator for your templating instead?

As I mentioned replacing syntax is not solution. I have solved this by rendering component presentation in separate C# tbb before Dreamweaver template. Off course,David suggestion is useful if you are allowed to change the syntax.

I use SDL Tridion 2011 SP1 HR1. TemplateBuilder version 6.1 Build 6.1.0.73.
Extract components from Page executed before DWT code below.
<!-- TemplateBeginRepeat name="Components" -->
##RenderComponentPresentation()##
<!-- TemplateEndRepeat -->
Output error logged from Template builder in case if component presentations contains ${sometext}.
JScriptException: Expression '""["scopedTarget.personalia"]."" != ""' had error 'Expected identifier'
at Tridion.ContentManager.Templating.Expression.JScriptEvaluator.EvaluateToObject(String statement)
at Tridion.ContentManager.Templating.Expression.JScriptEvaluator.EvaluateToString(String statement)
at Tridion.ContentManager.Templating.Package.EvaluateExpression(String expression)
at Tridion.ContentManager.Templating.Dreamweaver.DreamweaverMediator.TransformValueReferences(Package package, StringReference templateReference, Regex startTagExpression, String endTag)
at Tridion.ContentManager.Templating.Dreamweaver.DreamweaverMediator.TransformRegions(Package package, String dreamweaverTemplate)
at Tridion.ContentManager.Templating.Dreamweaver.DreamweaverMediator.Transform(Engine engine, Template templateToTransform, Package package)
at Tridion.ContentManager.Templating.Engine.ExecuteTemplate(Template template, Package package)
at Tridion.ContentManager.Templating.Engine.InvokeTemplate(Package package, TemplateInvocation templateInvocation, Template template)
at Tridion.ContentManager.Templating.Compound.CompoundTemplateMediator.Transform(Engine engine, Template templateToTransform, Package package)
at Tridion.ContentManager.Templating.Engine.ExecuteTemplate(Template template, Package package)
at Tridion.ContentManager.Templating.Engine.InvokeTemplate(Package package, TemplateInvocation templateInvocation, Template template)
at Tridion.ContentManager.Templating.Engine.TransformPackage(Template template, Package package)
at Tridion.ContentManager.Templating.Debugging.DebuggingEngine.Run()
at Tridion.ContentManager.Templating.Debugging.DebugSession.Run()
---Caused by:
Expected identifier
eval code: Line 1 - Error: Expected identifier

Related

How use a defined PPT template on PPTXGEN

I have a defined template, and I want to use it on the ppt exported using PPTXGEN LIBRARY.
is it possible ?
Only if you convert your template to (i.e. implement your template in) Javascript.
I found a python package here: python-pptx-text-replacer
If you are in an company, there's a commercial package called docxtemplate.

BundleTransformer for less complaining "Could not find a factory, that creates an instance of the JavaScript engine"

If you upgrade from version 1 to version 2 of BundleTransformer you may get this message:
Could not find a factory, that creates an instance of the JavaScript
engine with name MsieJsEngine.
Like me, you may not even have realized you've upgraded more than just a point release.
How to fix?
Version 2 DOES NOT USE WEB.CONFIG for configuration anymore
So start by removing it and read the rest of this link
https://github.com/Taritsyn/JavaScriptEngineSwitcher/wiki/How-to-upgrade-applications-to-version-2.X
Basically you will be doing the following:
Removing existing web.config nodes for javscript engine
Adding to someplace like global.asax some initialization code
Install Nuget packages for the engines you want to use
Make sure to add a using statement to be able to use extension methods (if you choose that way)
I ended up with something like this:
using JavaScriptEngineSwitcher.Core;
using JavaScriptEngineSwitcher.Msie;
using JavaScriptEngineSwitcher.V8;
....
public class JsEngineSwitcherConfig
{
public static void Configure(JsEngineSwitcher engineSwitcher)
{
engineSwitcher.EngineFactories
.AddMsie(new MsieSettings
{
UseEcmaScript5Polyfill = true,
UseJson2Library = true
})
.AddV8();
engineSwitcher.DefaultEngineName = MsieJsEngine.EngineName;
}
}
I'm following the instructions, but my code is now breaking on BundleConfig
var cssTransformer = new StyleTransformer();
In the name attribute of /configuration/bundleTransformer/less/jsEngine configuration element not specified a name of JavaScript engine.
If you have not installed JavaScript engine, then for correct working
of this module is recommended to install one of the following NuGet
packages: * JavaScriptEngineSwitcher.Msie *
JavaScriptEngineSwitcher.V8 * JavaScriptEngineSwitcher.ChakraCore
After package is installed, need set a name of JavaScript engine (for
example, MsieJsEngine) to the name attribute of
/configuration/bundleTransformer/less/jsEngine configuration
element.

Visual Studio treat custom extension as CSharp

I've got files with a custom extension .mcsx that are really CSharp files. I want to get code completion on these files in Visual Studio 2012, but these files are treated as plain text when I open them in VS.
I've tried to create a custom MEF extension which allows me to treat the files as having a content-type based on csharp, but I don't get autocompletion or code formatting for these documents. I might need to invoke the custom CSharp classifier for my custom content type, but I'm not sure. Can anyone help?
The custom ContentType is below:
static class ContentType
{
public const string Name = "CSScript";
[Export]
[Name(Name)]
[DisplayName("CSharp Script")]
[BaseDefinition("CSharp")]
public static ContentTypeDefinition CSharpContentType = null;
[Export]
[ContentType(Name)]
[FileExtension(".mcsx")]
public static FileExtensionToContentTypeDefinition CSharpFileExtension = null;
}
Thanks to 'Ego' on the VS forums:
You can add the custom extension file via the way below:
http://blogs.msdn.com/b/zainnab/archive/2010/08/22/using-custom-file-extension-associations-vstipenv0038.aspx
For more information about Registering a Language Service please view:
http://msdn.microsoft.com/en-us/library/vstudio/bb166421(v=vs.110).aspx
So inside of VS things are actually a bit different than the editor APIs imply -- we don't actually use content types (for the most part) to determine when to activate. Noah Richards has a great blog post that shows how to create an extension that marks another extension under an existing editor.

Dump Tridion Component as XML

What is the simplest way of dumping Tridion component content (based on a given schema, i.e.: non-arbitrary) into XML using modular template?
Specifically, need to pass component's content to/as ASP.Net custom control, that is, something like:
<custom:MyControl runat="server"
TextField="value1"..>
<EmbeddedField>
..
</EmbeddedField>
</custom:MyControl>
I see one possible way would be to tweak Default Dreamweaver Component Design DWT TBB, but that seems to be too laborious.
EDIT
Another murky subject was the second part of the question above: embedding XML into ASP.Net control markup. The problem is that XML needs to be escaped. The following brainteaser does it in a DWT (pressuming, that Nuno's TBB wrote into Output):
<custom:MyControl runat="server">
<xml>
##(Output).replace(RegExp.call(null, /&/.toString()[1], "g"), '&').replace(RegExp.call(null, /</.toString()[1], "g"), '<').replace(RegExp.call(null, />/.toString()[1], "g"), '>').replace(RegExp.call(null, String.fromCharCode(34), "g"), '"')##
</xml>
</custom:MyControl>
(All that ado is only necessary to overcome DWT's arcane JS escaping rules.)
Create a c# Template Building Block with the following code in it:
TemplatingLogger log = TemplatingLogger.GetLogger(GetType());
if (package.GetByName(Package.ComponentName) == null)
{
log.Debug("Not running in a Component Template, exiting.");
return;
}
Component component = (Component)engine.GetObject(package.GetByName(Package.ComponentName));
package.PushItem(Package.OutputName, package.CreateStringItem(ContentType.Xml, component.Content.OuterXml));
And use it in your template without any other building blocks.
This will output the exact content of Component.Content, which is rarely what you really want (for instance, how do you deal with binaries or linked components?), so you'll want to evolve to something else, with more details, and possibly removing the namespace from the XML nodes too...
i typically use a large switch(field.GetType().Name) and then deal with each field type as appropriate, something along these lines:
foreach (ItemField field in content)
{
string fieldType = field.GetType().Name;
switch (fieldType)
{
case "XhtmlField":
// do something, like write it to an XmlWriter
break;
And so on and so forth.
I would use the XSLT mediator and then make an XSLT TBB using <xsl:copy-of select="."/>
If you don't have the XSLT Mediator installed, it will be simpler to write a C# TBB with outputs the .Content property of the Component to the package with the name Output. See Nuno's code sample for more details.

Issue in accessing package variable in Dreamweaver Template

I am facing a issue in accessing a package variable in DWT of Page Template.
I have a compound page template with 4 TBB's as follows:
1) Constant TBB - This TBB reads all values of a component(Embedded multivalued component) as key-value pairs and pushes them to a package.
E.g :
Item item = this._package.CreateStringItem(contentType, "test");
this._package.PushItem("key", item);
2) C# DLL of Page Template - This contains the logic of Page Template
3) DWT of Page Template - All package variables are outputted here.
4) Default Finish Actions
The issue I am facing is as follows:
In my DWT ,I want to compare the Metadata of Component template with the package variable set in Constant TBB.
The syntax I am using is :
<!-- TemplateBeginIf cond="ComponentTemplate.Metadata.section_name = key" -->
where key is the package name set in constant TBB having value "test"
But somehow this package variable "key" is giving a value of 0 and not test.
Can someone let me know where exactly I am going wrong.
You should specify the type of item that you're adding to the package by replacing:
Item item = this._package.CreateStringItem(contentType, "test");
with
Item item = this._package.CreateStringItem(contentType.Text, "test");
You should also confirm that the variable is being passed properly to DWT by using
##test##
outside of the condition. This will show the value that you're comparing it to.
Please check following.
Check if there more than one variable in a package with "Key" name.
check if you verifying at correct place in package.

Resources