invalid type literal import - How to import and use my custom service - m2doc

So I created a simple service with a single class, without constructor : services.RecursiveQuery and added it as a plugin to my Eclipse instance as described in this question.
According to the documentation the next step would be to import it in my template file file so I tried this:
{m:import:services.RecursiveQuery}
However I get this error in the validation file:
Expression "import:services.RecursiveQuery:services" is invalid: invalid type literal import:
What am I doing wrong ? It feels like I'm missing something. Also I was wondering how to use the getAllChildren() method of this service. I would have tried
{m:for child | services.RecursiveQuery.getAllChildren(self)} but that doesnt feel right.

The M2Doc documentation may be unclear on this point: {m:import...} is not a valid statement in a M2Doc template file. It should be used in MS Word document properties, not in the docx template file.
You should use the template properties wizard to change imports along with the solution you mentionned here.
For a better understanding of how to use custom services you can check examples in M2Doc sources.

Related

How to automate M2Doc generation including the settings?

I've applied the guidance on programmatic usage of M2Doc (also with this help) to successfully generate a document via the API, which was previously prepared by using the M2Doc GUI (configured .docx plus a .genconf file). It seems to also work with a configured .docx, but without a .genconf file.
Now I would like to go a step further and ease the user interface in our application. The user should come with a .docx, include the {m:...} fields there, especially for variable definition, and then in our Eclipse application just assign model elements to the list of variables. Finally press "generate". The rest I would like to handle via the M2Doc API:
Get list of variables from the .docx
Tell M2Doc the variable objects (and their types and other required information, if that is separately necessary)
Provide M2Doc with sufficient information to handle AQL expressions like projectmodel::PJDiagram.allInstances() in the Word fields
I tried to analyse the M2Doc source code for this, but have some questions to achieve the goal:
The parse/generate API does not create any config information into the .docx or .genconf files, right? What would be the API to at least generate the .docx config information?
The source code mentions "if you are using a Generation" - what is meant with that? The use of a .genconf file (which seems to be optional for the generate API)?
Where can I get the list of variables from, which M2Doc found in a .docx (during parse?), so that I can present it to the user for Object (Model Element) assignment?
Do I have to tell M2Doc the types of the variables, and in which resource file they are located, besides handing over the variable objects? My guess is no, as using a blank .docx file without any M2Doc information stored also worked for the variables themselves (not for any additional AQL expressions using other types, or .oclAsType() type castings).
How can I provide M2Doc with the types information for the AQL expressions mentioned above, which I normally tell it via the nsURI configuration? I handed over the complete resourceSet of my application, but that doesn't seem to be enough.
Any help would be very much appreciated!
To give you an impression of my code so far, see below - note that it's actually Javascript instead of Java, as our application has a built-in JS-Java interface.
//=================== PARSING OF THE DOCUMENT ==============================
var templateURIString = "file:///.../templateReqs.docx";
var templateURI = URI.createURI(templateURIString);
// canNOT be empty, as we get nullpointer exceptions otherwise
var options = {"TemplateURI":templateURIString};
var exceptions = new java.util.ArrayList();
var resourceSetForModels = ...; //here our application's resource set for the whole model is used, instead of M2Doc "createResourceSetForModels" - works for the moment, but not sure if some services linking is not working
var queryEnvironment = m2doc.M2DocUtils.getQueryEnvironment(resourceSetForModels, templateURI, options);
var classProvider = m2doc.M2DocPlugin.getClassProvider();
// empty Monitor for the moment
var monitor = new BasicMonitor();
var template = m2doc.M2DocUtils.parse(resourceSetForModels.getURIConverter(), templateURI, queryEnvironment, classProvider, monitor);
// =================== GENERATION OF THE DOCUMENT ==============================
var outputURIString = "file:///.../templateReqs.autogenerated.docx";
var outputURI = URI.createURI(outputURIString);
variables["myVar1"] = ...; // assigment of objects...
m2doc.M2DocUtils.generate(template, queryEnvironment, variables, resourceSetForModels, outputURI, monitor);
Thanks!
No the API used to parse an generate don't modifies the template file nor the .genconf file. To modify the configuration of the template you will need to use the
TemplateCustomProperties class. That will allow you to register your metamodels and service classes. This instormation is then used to configure the IQueryEnvironment, so you might also want to directly configure the IQueryEnvironment in your code.
The generation in this context referes to the .genconf file. Note The genconf file is also an EMF model, so you can also craft one in memory to launch you generation if it's easier for you. But yes the use of a .genconf file is optional like in your code example.
To the list of variables in the template you can use the class TemplateCustomProperties:
TemplateCustomProperties.getVariables() will list the variables that are declared with their type
TemplateCustomProperties.getMissingVariables() to list varaibles that are used in the template but not declared
You can also find le list of used metamodels (EPackage nsURIs) and imported services classes.
The type of variables is not needed at generation time, it's only needed if you want to validate your template. At generation time you need to pass a map from the variable name to its value as you did in your example. The value of a variable can be a any object from your model (an EObject), a String, an Integer, ... If you want to use something like oclIsKindOf(pkg::MyEClass) you will need to register the nsURI of pkg first see the next point.
The code you provided should let you use something like projectmodel::PJDiagram.allInstances(). This service needs a ResourceSetRootEObjectProvider() that is initialized in M2DocUtils.getQueryEnvironment(). But you need to declare the nsURI of your metamodel in your template (see TemplateCustomProperties). This will register it in the IQueryEnvironment. You can also register it yourself using IQueryEnvironment.registerEPackage().
This should help you finding the missing parts in the configuration of the AQL environment. Your code seems good and should work when you add the configuration part.

drf-yasg Customize SwaggerUIRenderer

I'd like to customize the style (font, colors, logo, etc) of drf_yasg generated docs.
I see that I can extend drf_yasg/swagger-ui.html with the blocks extra_head, extra_styles, extra_body, extra_scripts, and can even overwrite the other blocks if I need to.
What I am not clear on is how I point to my template that extends swagger-ui.html.
I started with
class MyCustomSwaggerUIRenderer(SwaggerUIRenderer):
template = 'api/custom-swagger-ui.html'
I want to replace SwaggerUIRenderer with MyCustomSwaggerUIRenderer in get_schema_view but do not understand how/where to do it without explicitly trying to enumerate all the other Renderers required too in some subclass of rest_framework.views.APIView and that seems convoluted.
Pointers to docs or examples are appreciated. I've already read https://drf-yasg.readthedocs.io/ without success.
You don't have to create a custom class for this. You just need to create a directory with the name drf-yasg under new or existing app and then place a file with the name swagger-ui.html underneath it with your custom template. For example, if you already have an app with the name api, you can just put it under api/templates/drf-yasg/swagger-ui.html. Make sure the app api is specified before drf-yasg in INSTALLED_APPS.
Reference: https://github.com/axnsan12/drf-yasg/issues/294#issuecomment-464461773

ember Error: Compile Error: is not a helper

I got the following error while developing our front-end with Ember.js:
ember Error: Compile Error: '...' is not a helper
What is the meaning of this error?
Reason
Ember throws this error if there is no component or helper with the given name is not found in your project or your dependent addons.
How to solve
You should check the name of the component or helper that you have written (possible errors are spelling errors or writing directory structure of the component incorrectly).
This twiddle shows example of this error message when the component my-component is called as {{my-component2 x=x}} instead of {{my-component x=x}} mistakenly.
This error can also happen in older (pre-Octane) versions of Ember if you have your component in all the right places, but your component doesn't have a dash in its name. As per the docs, components are required to have at least one dash in their names:
Components must have at least one dash in their name. So blog-post is an acceptable name, and so is audio-player-controls, but post is not. This prevents clashes with current or future HTML element names, aligns Ember components with the W3C Custom Elements spec, and ensures Ember detects the components automatically.
If you try to create a component without a dash in its name, Ember won't find it and will give you this error.
It appears this requirement has been lifted in more recent versions of Ember, where components start with a capital letter to distinguish them from native HTML elements.
From the documentation:
Helpers allow you to add additional functionality to your templates beyond what is included out-of-the-box in Ember. Helpers are most useful for transforming raw values from models and components into a format more appropriate for your users.
It looks like you are using a non-defined helper. So please look through (and maybe provide) some more of your log output. You are probably using an undefined helper in one (or multiple) of your .hbs-files.
component and file name must be the same. This solution worked for me.

Code-completion support for Django template language in Pycharm

In the template files code-completion works well for html tags and for adding matching {%,
What I want is for eg: if I type blog. and Ctrl + Space, it should show me the options like blog_title,blog_author etc, that are associated with blog.
Is this possible at all?
I do not think it is possible as PyCharm has no knowledge of the type of objects you pass as context to the template. It could infer it from the view where the template is used but we are not there yet.
It is possible if you register your own template tags with explicit name in your code.
Example: register.tag ("page_attribute", PageAttribute)
See also: https://github.com/divio/django-cms/issues/3878 where the same thing came up.
PyCharm will recognize that and do as you asked.

How do I tell Dojo build to ignore a 'missing' template

Our application has a number of widgets that use templates that are generated on the fly via a JSP.
In the front-end code, they are included using the dojo/text plugin. This ensures that Widget lifecycle isn't kicked off until the template has been resolved and it works just fine.
Unfortunately, when we try to perform our build, we get a 311 error:
error(311) Missing dependency. module:
app/navigation/NavigationManager; dependency:
dojo/text!/author/app/templates/NavigationManager-content.html; error:
Error: text resource
(/author/app/templates/NavigationManager-content.html/x) missing
I understand what's happening here, the build process is trying to internalize the string, but when it goes to look for it, it can't locate it and so flags it as a missing dependency.
I see a number of options here:
Somehow, tell Dojo to ignore this missing dependency - this would be fine, but I'd need to be able to be specific, so that I get alerted to any other dependencies that might be missing
Somehow, tell Dojo not to try and internalize this template - this would also be fine, since there's nothing to internalize here.
Somehow, stub out the dependency so that the dependency resolution passes, but the internalization doesn't occur.
I've seen references to the
internStringsSkipList
value, but none of the following helped:
internStringsSkipList: ['/author/pepper/templates/NavigationManager-content.html']
internStringsSkipList: ['dojo/text!/author/pepper/templates/NavigationManager-content.html']
internStringsSkipList: ['/author/pepper/templates/NavigationManager-content.html/x']
Any suggestions?
I faced exactly the same problem and after reading lots of dojo documentation and source code I came to the conclusion that it's very difficult if almost impossible to do. There is, however, a very simple and elegant workaround. But before telling you how to solve the problem firstly why there is a workaround needed in the first place (so you can adjust the solution to your own circumstances):
First issue, the resource is undiscoverable
According to the Overview section of the dojo build system Reference Guide:
[The build system] “discovers” a set of resources and then applies a synchronized, ordered set of resource-dependent transforms to those resources. (…) When a resource is discovered, it is tagged with one or more flags that help identify the role of that resource. (…) After a resource is discovered and tagged, the system assigns a set of transforms that are to be applied to that resource.
So in short, any resources generated on the fly can't be discovered by the build system because they don't reside on the file system. If they can't be discovered, then they can't be tagged and no transformation can be applied to it. In particular, resourceTags is not called for such resources and you can't put them on the exclude list of a profile layer definition (compare section Layers in Creating Builds).
BTW, as far as I understand the documentation to depsScan transform, internStringsSkipList can only be used to skip resources specified using the legacy notation (dojo.something, e.g. dojo.moduleUrl).
Second issue, the plugin resolver expects a physical file
Notation dojo/text!/some/url says to use the dojo/text.js component as a plugin. I found this note in this ticket:
Every AMD plugin should have a plugin resolver in util/build/plugins and have it registered in util/build/buildControlDefault.
If you check util/build/plugins/text.js (e.g. on Github) you'll see that the error is being thrown because the dependency (that part after dojo/text! is stored in moduleInfo) is not in the resources array:
textResource = bc.resources[moduleInfo.url];
if (!textResource){
throw new Error("text resource (" + moduleInfo.url + ") missing");
}
And this is precisely because the resource couldn't be discovered during the "discovery" phase.
The difficult solution
In the difficult solution, that might or might not work, you would need to change how the transformation depsScan works. Basically, when depsScan encounters dojo/text!/some/url it calls the plugin resolver to check if the dependency exists. From the depsScan documentation:
Once all dependencies are found, the transform ensures all dependencies exist in the discovered modules. Missing dependencies result in an error being logged to the console and the build report.
That might be possible by redefining transformJobs to contain a custom transform for depsScan. See util/build/buildControlDefault.js (on Github) and this forum post for more insights.
The simple workaround
Just create your own plugin to load the resource. Your own plugin won't have the plugin resolver registered (see the second issue above) and all you'll get when compiling is the dreaded
warn(224) A plugin dependency was encountered but there was no build-time plugin resolver.
This is my example of such plugin that loads a JSON resource dynamically:
define(["dojo/text", "dojo/_base/lang", "dojo/json"],
function(text,lang,json){
return lang.delegate(text, {
load: function(id, require, load){
text.load(id, require, function(data){
load(json.parse(data));
});
}
});
});
It reuses dojo/text adding its custom load function. This is an adaptation of another example posted on this dojo-toolkit forum post. You can see their code on JSFiddle.
In my project I use the plugin like this:
define(["./json!/path/to/an/json"],
function(values){
return values;
});
Your plugin can just return the loaded template without parsing it as JSON, and as long as you don't specify your custom plugin resolver (which would expect the file to exist physically on disk) the project will compile fine.
This wasn't your issue, but the most common solution to those facing the error(311) problem is going to be this:
Don't start template paths with a slash.
Bad:
"dojo/text!/app/template/widget.html"
Good:
"dojo/text!app/template/widget.html"
Your template path isn't a normal, plain-ol' URL. It's still part of the Dojo build, so you use Dojo build pathing to get to the template.