Is it possible to use the same module under different names in RequireJS? (Mostly interested in optimized version)
Example
I depend on an AMD-compatible library that depends on lodash. I already have underscore in my code and I want that library to use it instead of lodash.
Of course I do not want modify library's source. So I modify the require.js configuration:
paths: {
'underscore': 'vendor/underscore', // that's for my code
...
'lodash': 'vendor/underscore', // that's for the new library
}
And now when trying to build, r.js throws the unfortunate:
The following modules share the same URL.
This could be a misconfiguration if that URL only has one anonymous module in it:
/.../underscore.js: lodash, underscore
Is there a way to register the same module under 2 or more different names?
In general it is not safe to load Underscore for code that requires Lodash. The one exception is if you are 100% sure that the code in question used Lodash in its Underscore-compatible mode.
If you have determined that it is safe in your specific case, then I would handle your specific problem by using a map:
map: {
"*": { 'lodash': 'underscore'}
}
This tells RequireJS that everywhere lodash is required, give back underscore instead.
The method above returns a single module instance if lodash or underscore are required. It would not work in a case someone would want to load the same module code twice under two different names and would want to keep module state separate. For instance, a module which is meant to register names. If someone would want to load this module under names foo and bar and keep the two registries separate so that what is registered in foo is but not registered in bar is not in bar (and vice-versa) then they would need two module instances and thus would have to do something else than use map.
Related
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.
I need to change short month in moment.
But I can't do it.
I have try to set
localeOutputPath: 'assets/moment-locales'
And call
Ember.$.getScript('/assets/moment-locales/ru.js');
In this case i have ember-mirage error
Your Ember app tried to GET '/assets/moment-locales/ru.js?_=1490191145335',
but there was no route defined to handle this request. Define a route that
matches this path in your mirage/config.js file
Is it simple way to set short months name for moment?
I assume you are using ember-moment addon; and already have configured config/environment.js with
moment: {
// This will output _all_ locale scripts to assets/moment-locales
localeOutputPath: 'assets/moment-locales'
},
as you have mentioned.
Ember.$.getScript('/assets/moment-locales/ru.js');
provides a way to dynamically load moment ru locale on the fly when needed. This means instead of including the related locale to your application's javascript file you prefer to load relevant locale upon some user request in your application. Generally it is best to perform such loading operation within a router's hook methods such as beforeModel or model.
In order to get short month names from moment; you need to first import ES6 moment module via
import moment from 'moment';
and access the short month names with
moment.monthsShort()
As far as I can see; there is a problem with the way you are requesting the locale so you are getting the error you have mentioned. I believe a working code is a better explanation from pure text; hence I have created the following git repository to illustrate how you can change the locale dynamically in a route and how you can display short names retrieved from moment. Please take a look at it by cloning and running in your localhost.
In the application at this repository, application.hbs contains links to 5 sub-routes; each displaying short names of months in different languages. The code that does the trick of dynamically loading the relevant locale is in routes/locale-route.js file's model hook method. If locale is already loaded (note that English is included by default with moment) it simply returns the short names of the months via switching to target locale (moment.locale(localeToLoad);). Otherwise, it performs a remote call to the server and waits for the response (by using a promise) to return the name of months. All routes for 5 different languages extend from this base route. Once, a locale is loaded from the server; you no longer need to load it again once more and the locale-route already handles it as I explained. I hope that helps.
After reading your comment; I updated the source code to include ember-cli-mirage. Mirage is a client-side mock server to develop, test and prototype your application. Once you include it as a dependency it starts intercepting your remote call requests. Hence, in your case mirage intercepts requests for demanding related locale. What you need to do is passing through mirage for locales. In order to do that, you need to add following
this.passthrough('/assets/moment-locales/**');
to mirage/config.js so that mirage will not interfere with demanding moment-locales at the runtime. Please see related file under the git repository I have provided. This will solve your problem for sure.
Creating in-repo-addon in Ember.JS gives a lot of possibilities. Today I've stumbled into a case when I wanted to register all classes in directory (for example my-dir) into Dependency Injector (same way it's done with services by Ember, but I wanted to use some other namespace).
For example I want to allow developer to create multiple classes inside proxy directory, and register all of them in DI under proxy: namespace. So later we can use:
Ember.Component.extend({
myProxy: Ember.inject('proxy:my'),
});
You'll need to do this using an initializer. More details on this here: https://guides.emberjs.com/v2.12.0/applications/dependency-injection/
The hard part may be getting all proxy items in s folder to automatically register ...
Edit
Looks like I didn't spend enough time thinking about this. You should be able to do at least part of this easily. There are two parts to this.
Part 1
Ember currently uses the ember-resolver to handle lookups for various items. If you check the tests for the resolver you'll notice that you should be able to map in anything you want: https://github.com/ember-cli/ember-resolver/blob/master/tests/unit/resolvers/classic/basic-test.js
So in your case, if you do a Ember.getOwner(this).lookup('proxy:main') from within an Ember instantiated class (a route, controller or component for instance) it would look in app/proxy/main.js which your addon could be populating.
Details on the Ember.getOwner lookup are available here: https://emberjs.com/api/classes/Ember.html#method_getOwner
Part 2
So at this point you can lookup proxies (which would be doable in an init method). But if we want to get truly elegant we'd want to allow Ember.inject.proxy('main') syntax.
Doing so would involve calling a private method inside of Ember.inject in an initializer. Because that naming scheme is changing in the new Javascript modules RFC, it may be unwise to try to add this syntactic sugar ...
So I'd advise avoiding touching that private API unless it's really important to your app design.
I'm trying to make my own full adder and some other devices as a sub-circuit in "Proteus" and use them several times in a bigger circuit.
The problem is when you copy a sub-circuit you need to rename all of its inner parts, otherwise, the parts with a same name in two sub-circuits would be considered as one, therefore you'd get some errors.
So I'd like to know if there is a way to define a full adder of my own and use it like "74LS183" which is a primitive device, and by primitive I mean it has been defined in the library.
From answer posted here
It's in the Proteus Help file:
SCHEMATIC CAPTURE HELP (F1) -> MULTI-SHEET DESIGNS -> Hierarchical Designs
See the section "Module Components":
Any ordinary component can be made into a module by setting the Attach Hierarchy Module checkbox on the Edit Component dialogue form.
The component's value is taken to be the name for the associated circuit,
and the component's reference serves as the instance name.
after this you can use your new implementation of that component with your new name. for making it available at library see "External Modules" section of proteus help.
The problem with copying is solved in "Proteus 8".not completely but sort of.
I mean you can copy a subcircuit without a need to change it's inner parts, but you must change the subcircuit name and I mean the bigger name above the subcircuit not the little one below it.
so there is no need to define a primitive.
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.