What is the origin of $generalUtil in my atlassian-plugin.xml? - velocity

I'm studying the code of a custom Confluence plugin, which contains an atlassian-plugin.xml file that includes references to two variables $generalUtil and $helper, but I find no definitions of them whatsoever in the entire project. They simply work and it appears to me that they are magically instantiated out of thin air.
<web-item key="configtab" name="configtab" section="system.space.tools/addons">
<label key="myplugin.space.tools.addons.tab.label" />
<link>/spaces/myplugin-config.action?spaceKey=$generalUtil.urlEncode($helper.spaceKey)</link>
</web-item>
The $generalUtil must be an instance of com.atlassian.confluence.util.GeneralUtil, which also has a method urlEncode(). But where does this variable originate from?
What puzzles me even more is the $helper, which has a spaceKey field/method that I find in the code, but without any relationship to any kind of Helper class. The $helper also appears in a velocity template, but also without any definition of it. Any ideas where this stuff is documented?

generalUtil is documented here: https://docs.atlassian.com/ConfluenceServer/javadoc/7.11.6/
I think helper is https://docs.atlassian.com/ConfluenceServer/javadoc/7.11.6/com/atlassian/confluence/themes/GlobalHelper.html
They are injected into the Velocity context used to render that link.

Related

Piranha CMS: Problem with custom block in manager interface

I am trying to add a custom block. I followed the steps in following two links:
http://piranhacms.org/docs/extensions/blocks
and
http://piranhacms.org/docs/manager-extensions/resources
In the CMS manager, I added the custom block to a page, but the block content is empty. Looks like the Vue.js didn't get associated to the custom block. I have set the block component attribute to the Vue.js.
I added the Vue.js by calling below method in the startup. Did I miss something to create a custom block?
App.Modules.Get<Piranha.Manager.Module>().Scripts.Add("~/assets/js/myscripts.js");
Move your "mycustomblock.js" file to the folder "wwwroot/js/" instead of the default "assets/js/". That way the file will be visible to Vue.js
Something is not working with the assets folder, probably it cannot be reached by Vue.js
after the Project is compiled. I had the same problem and this solution worked for me.
void Configure in Startup.cs will then look something like this (I simplified the syntax a bit compared to the documentation):
App.Modules.Manager().Scripts.Add("~/js/mycustomblock.js");
Adding a custom block and many other tasks have been difficult for me. Trial and error, and no knowledgebase to fall back on. The documentation is a fantastic start, and "Step by step" guides would be a good idea for the future (but I guess time is very limited).

What 'expression:' property in QML Item

I've inherited a collection of mostly undocumented QML code. I'm new to QML, and I'm struggling to understand this code. In particular, the construct
expression: "connected == false"
occurs frequently in various items, but I can't find any documentation on what this property does. It does not seem to be defined anywhere in the existing code collection, so I'm assuming it's part of QML, but I'm having no luck turning it up anywhere.
It looks as though all items using this construct are backed by C++ classes. However, "expression" is not defined as a QPROPERTY anywhere in the C++ code.
Nope, there's no such property in QML. You'll have to look into the QML file for the type that it's used in, or the C++ if it's declared there.

TypeScript Intellisense works differently if I define Object in Different Ways

I am trying to convert some existing JavaScript code by using TypeScript, One example I am using is to create Highcharts classes, the Highcharts definition is from https://github.com/borisyankov/DefinitelyTyped/blob/master/highcharts/highcharts.d.ts
We all know HighchartsOptions has a property title.
If I define the object in this way, I have intellisense
But if I define object this way
I don't have the intellisense.
Any specific reason why Visual Studio behaves differently?
It's just a bug. See this issue on CodePlex to track when it gets fixed.

Setting local int variable's value to Int.MaxValue in xaml

I was wondering how I can set a local int variable's value to Int.MaxValue in xaml (which is in the ResourceDictionary in my case).
something like: (but something that works :) )
xmlns:s="clr-namespace:System;assembly=mscorlib
<s:Int32 x:Key"HelloWorld">{x:Static s:Int.MaxValue}</s:Int32>
EDIT:
#Ian:
Thank you :)
But how do I use the static resource as an int?
let's say if I have in my ResourceDictionary
<ResourceDictionary>
<x:Static
x:Key="HelloWorld"
Member="s:Int32.MaxValue"
/>
...
<blablalba TooltipService.ShowDuration="{StaticResource HelloWorld}"/>` <-- this does not work by the way
</ResourceDictionary>
This should do it:
<x:Static
x:Key="HelloWorld"
Member="s:Int32.MaxValue"
/>
Just in case it's not clear what's actually happening here, it's using a handy trick that a lot of people don't know about: although markup extensions like x:Static are normally used in attributes inside braces ({}) you can also use the element syntax for them. This is useful in situations like these where you want to use a markup extension, but the Xaml syntax expects an element. (It's most often necessary in scenarios involving collections, like this one.)
The one slight gotcha with using element syntax for markup extensions is that you no longer get to pass in constructor arguments. (Technically, constructor argument support was introduced in XAML 2009, which has been supported since .NET 4. However, it's only supported if you load Xaml via the new Xaml APIs. The MSDN documentation says that the new XAML 2009 features are not supported for compiled Xaml in WPF.) So you can only use this trick with markup extensions that offer default constructors, and which provide properties that can be used instead of constructor arguments. The StaticExtension provides a Member property that does the trick, so we're OK here, but be aware that sometimes, you'll be stuck due to the inability to call the appropriate constructor.
Note that as you type this in, the Xaml IntelliSense in Visual Studio will probably suggest StaticExtension, which is the real name of this markup extension. When you use the attribute syntax, it leaves off the Extension part, but with elements, it seems not to, for some reason. Either form is correct though - I'd go with what I've written here and not what IntelliSense suggests, because we're more accustomed to seeing "{x:Static ...}" in attributes than "{x:StaticExtension ...}" - again, both are legal, but idiomatically, we tend to leave off the Extension.
You were so close first time, just turns out you missed the 32 from Int32
<blablalba TooltipService.ShowDuration="{x:Static s:Int32.MaxValue}"/>
The other solution of adding a static resource seems a bit ridiculous - you're essentially creating a static resource as a wrapper around an existing static property...
The problem is that there is no class Int If you try with Int32 it works
As such.
<Button>
<ToolTipService.ShowDuration>
<x:Static Member="sys:Int32.MaxValue" />
</ToolTipService.ShowDuration>
</Button>

Are the contents of a fragment visible outside the host plugin?

I have never worked with plug-in fragments before. I thought that by creating a new class within a fragment and exporting the package that contains it in the fragment's manifest, I'd be able to access that class from another plug-in that already has a dependency on the host plug-in. However, I cannot seem to make this work. Are the contents of a fragment ever visible to any plug-in besides the host plug-in? If so, is there something special I have to do to allow this?
The problem is not, that the contents of the fragment aren't visible to another plugin: They are - just try loading e.g. a properties file from the classpath, it still works if that properties file is provided by the fragment.
But what you don't have, is compile-time information about the fragment's contents. That's the principle of a fragment: You can't have a dependency on it. And you don't know, if somebody has fragments installed or not.
It's also not only a problem that just "any plug-in besides the host plug-in" has. It's a problem, that even the host-plugin itself has. It doesn't know about the fragment's existence at compile-time.
You also can't reliably use a fragment to override parts of the host plug-in's classes: FAQ Can fragments be used to patch a plug-in? , if that's what you want to do. The page also describes, how it can be done.
Hope this helps.