add snippets to language server - javascript

I want to add more keywords & snippets to autocomplete service.
e.g; If I type FooBar it will suggest
var FooBar = function (args) {
return `foo ${args.length}`;
};
how do I extend Language Server ?
If it matters, I'm using vim-lsp.
ref

You can write your own snippets using a snippets plugin. Vim-lsp recommends a few in :h vim-lsp. However, I do not believe there's any way to add snippets to a language server directly without modifying that server directly.
That being said, it may not be that hard to modify the server and add a few snippets. vim-language-server, for instance, seems to keep its snippets defined in a snippets.ts file here. Modifying this file might interfere with automatically updating the server, but it shouldn't cause any real problems unless you mess up the syntax. And then when you do want to update the server, just save your changes somewhere and undo them on this file and let it update, then add them back.

Related

Duplicate an HTML file (and its content) with a different name in Javascript

I have an HTML file with some Javascript and css applied on.
I would like to duplicate that file, make like file1.html, file2.html, file3.html,...
All of that using Javascript, Jquery or something like that !
The idea is to create a different page (from that kind of template) that will be printed afterwards with different data in it (from a XML file).
I hope it is possible !
Feel free to ask more precision if you want !
Thank you all by advance
Note: I do not want to copy the content only but the entire file.
Edit: I Know I should use server-side language, I just don't have the option ):
There are a couple ways you could go about implementing something similar to what you are describing. Which implementation you should use would depend on exactly what your goals are.
First of all, I would recommend some sort of template system such as VueJS, AngularJS or React. However, given that you say you don't have the option of using a server side language, I suspect you won't have the option to implement one of these systems.
My next suggestion, would be to build your own 'templating system'. A simple implementation that may suit your needs could be something mirroring the following:
In your primary file (root file) which you want to route or copy the other files through to, you could use JS to include the correct HTML files. For example, you could have JS conditionally load a file depending on certain circumstances by putting something like the following after a conditional statement:
Note that while doing this could optimize your server's data usage (as it would only serve required files and not everything all the time), it would also probably increase loading times. Your site would need to wait for the additional HTTP request to come through and for whatever requested content to load & render on the client. While this sounds very slow it has the potential of not being that bad if you don't have too many discrete requests, and none of your code is unusually large or computationally expensive.
If using vanilla JS, the following snippet will illustrate the above:
In a script that comes loaded with your routing file:
function read(text) {
var xhr=new XMLHttpRequest;
xhr.open('GET',text);
xhr.onload=show;
xhr.send();
}
function show() {
var text = this.response;
document.body.innerHTML = text;//you can replace document.body with whatever element you want to wrap your imported HTML
}
read(path/to/file/on/server);
Note a couple of things about the above code. If you are testing on your computer (ie opening your html file on a browser, with a path like file://__) without a local server, you will get some sort of cross origin request error when trying to make an XML request. To bypass this error, either test your code on an actual server (not ideal constantly pushing code, I know) or, preferably, set up a local testing server. If this is something you would want to explore, its not that difficult to do, let me know and I'd be happy to walk you through the process.
Alternately, you could implement the above loading system with jQuery and the .load() function. http://api.jquery.com/load/
If none of the above solutions work for you, let me know more specifically what it is that you need, and I'll be happy to give a more useful/ relevant answer!

Language switch in SAPUI5

I've got a language problem with my SAPUI5 controls.
If I execute e.g.:
sap.ui.getCore().getConfiguration().setLanguage("de");
My i18n files are loaded correctly and all labels are translated to German. But the controls are still in English.
The only way to get German controls is with the URL parameter:
sap-ui-language=DE
But I can't use a parameter in my case. Any idea?
Please note that sap.ui.getCore().setLanguage() explicitly states
The framework does not guarantee that already created, language dependent objects will be updated by this call. It therefore remains best practice for applications to switch the language early, e.g. before any language dependent objects are created. Applications that need to support more dynamic changes of the language should listen to the localizationChanged event and adapt all language dependent objects that they use (e.g. by rebuilding their UI).
Besides that, I fully support Nabi's answer (but I'm not allowed to vote it up).
I just would like to add that controls (like FilterBar) better should use the hook approach:
FilterBar.prototype.onlocalizationChanged = function(oEvent) {
// .. same bundle update code as in Nabi's proposal
}
Using the hook in controls avoids the need for adding attach + detach calls in init / exit and keeps the event registry small.
I can easily confirm the behavior you described by testing the Explored App Example. There, just open the console and hit sap.ui.getCore().getConfiguration().setLanguage("de");
I also checked the implementation of the FacetFilter and I would call this a bug in the Control implementation. It comes from how the texts are loaded inside the control. Just in case you are interested:
The message bundles all contain the correct translations for FACETFILTER_INFOBAR_NO_FILTERS (for en the translation comes from the "default" bundle):
messagebundle.properties
messagebundle_de.properties
The FacetFilter has a hidden aggregation called SummaryBar. The SummaryBar contains the text you see. Of course, this text comes from a bundle.
However, the bundle is initialized exactly once in init() by calling sap.ui.getCore().getLibraryResourceBundle("sap.m");. Here the API docs say:
If only one argument is given, it is assumed to be the libraryName.
The locale then falls back to the current session locale.
This means the bundle is cached and therefor changes to the localization (e.g. language) do not trigger the bundle to load a new translation file. Thus, we will always see the initial language no matter what we try (even rerendering() does not help).
A solution would be to fix the control by adding the following code right after the the bundle gets loaded inside the init:
sap.ui.getCore().attachLocalizationChanged(function(oEvent){
var oChanges = oEvent.getParameter("changes");
if (oChanges && oChanges.language){
this._bundle = sap.ui.getCore().getLibraryResourceBundle("sap.m", oChanges.language);
this.rerender();
}
}.bind(this));
You can try this out in the explored app linked above, it worked for me just fine...
I just opened an issue on github.

Is there a way to tell Google Closure Compiler to *NOT* inline my local functions?

Here's what I'm looking for:
I want to use the wonderful features of SIMPLE mode minification while disabling just one specific feature (disable local function inline).
UPDATE: The answer is NO, it's not possible given my setup. But for me there is a workaround given I am using Grails.
As #Chad has explained below, "This violates core assumptions of the compiler". See my UPDATE3 below for more info.
IN QUESTION FORM:
I'm using CompilationLevel.SIMPLE_OPTIMIZATIONS which does everything I want, except that it's inlining my local functions.
Is there any way around this? For example, is there a setting I can place in my JS files to tell Google Closure not to inline my local functions?
It would be cool to have some directives at the top of my javascript file such as:
// This is a JS comment...
// google.closure.compiler = [inlineLocalFunctions: false]
I'm developing a Grails app and using the Grails asset-pipeline plugin, which uses Google Closure Compiler (hereafter, Compiler). The plugin supports the different minification levels that Compiler supports via the Grails config grails.assets.minifyOptions. This allows for 'SIMPLE', 'ADVANCED', 'WHITESPACE_ONLY'.
AssetCompiler.groovy (asset-pipeline plugin) calls ClosureCompilerProcessor.process()
That eventually assigns SIMPLE_OPTIMIZATIONS on the CompilerOptions object. And by doing so, CompilerOptions.inlineLocalFunctions = true as a byproduct (this is hard coded behavior in Compiler). If I were to use WHITESPACE_ONLY the result would be inlineLocalFunctions=false.
So by using Asset Pipeline's 'SIMPLE' setting, local functions are being inlined and that is causing me trouble. Example: ExtJS ext-all-debug.js which uses lots of local functions.
SO post Is it possible to make Google Closure compiler *not* inline certain functions? provides some help. I can use its window['dontBlowMeAway'] = dontBlowMeAway trick to keep my functions from inlining. However I have LOTS of functions and I'm not about to manually do this for each one; nor would I want to write a script to do it for me. Creating a JS model and trying to identity local functions doesn't sound safe, fun nor fast.
The previous SO post directs the reader to https://developers.google.com/closure/compiler/docs/api-tutorial3#removal, where the window['bla'] trick is explained, and it works.
Wow thanks for reading this long.
Help? :-)
UPDATE1:
Okay. While spending all the effort in writing this question, I may have a trick that could work. Grails uses Groovy. Groovy makes method call interception easy using its MetaClass API.
I'm going to try intercepting the call to:
com.google.javascript.jscomp.Compiler.compile(
List<T1> externs, List<T2> inputs, CompilerOptions options)
My intercepting method will look like:
options.inlineLocalFunctions=false
// Then delegate call to the real compile() method
It's bed time so I'll have to try this later. Even so, it would be nice to solve this without a hack.
UPDATE2:
The response in a similar post (Is it possible to make Google Closure compiler *not* inline certain functions?) doesn't resolve my problem because of the large quantity of functions I need inlined. I've already explained this point.
Take the ExtJS file I cited above as an example of why the above similar SO post doesn't resolve my problem. Look at the raw code for ext-all-debug.js. Find the byAttribute() function. Then keep looking for the string "byAttribute" and you'll see that it is part of strings that are being defined. I am not familiar with this code, but I'm supposing that these string-based values of byAttribute are later being passed to JS's eval() function for execution. Compiler does not alter these values of byAttribute when it's part of a string. Once function byAttribute is inlined, attempts to call the function is no longer possible.
UPDATE3: I attempted two strategies to resolve this problem and both proved unsuccessful. However, I successfully implemented a workaround. My failed attempts:
Use Groovy method interception (Meta Object Protocol, aka MOP) to intercept com.google.javascript.jscomp.Compiler.compile().
Fork the closure-compiler.jar (make my own custom copy) and modify com.google.javascript.jscomp.applySafeCompilationOptions() by setting options.setInlineFunctions(Reach.NONE); instead of LOCAL.
Method interception doesn't work because Compiler.compile() is a Java class which is invoked by a Groovy class marked as #CompileStatic. That means Groovy's MOP is not used when process() calls Google's Compiler.compile(). Even ClosureCompilerProcessor.translateMinifyOptions() (Groovy code) can't be intercepted because the class is #CompileStatic. The only method that can be intercepted is ClosureCompilerProcessor.process().
Forking Google's closure-compiler.jar was my last ugly resort. But just like #Chad said below, simply inserting options.setInlineFunctions(Reach.NONE) in the right place didn't resurrect my inline JS functions names. I tried toggling other options such as setRemoveDeadCode=false to no avail. I realized what Chad said was right. I would end up flipping settings around and probably destroying how the minification works.
My solution: I pre-compressed ext-all-debug.js with UglifyJS and added them to my project. I could have named the files ext-all-debug.min.js to do it more cleanly but I didn't. Below are the settings I placed in my Grails Config.groovy:
grails.assets.minifyOptions = [
optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED
]
grails.assets.minifyOptions.excludes = [
'**ext-all-debug.js',
'**ext-theme-neptune.js'
]
Done. Problem solved.
Keywords: minify, minification, uglify, UglifyJS, UglifyJS2
In this case, you would either need to make a custom build of the compiler or use the Java API.
However - disabling inlining is not enough to make this safe. Renaming and dead code elimination will also cause problems. This violates core assumptions of the compiler. This local function is ONLY referenced from within strings.
This code is only safe for the WHITESPACE_ONLY mode of the compiler.
Use the function constructor
var fnc = new Function("param1", "param2", "alert(param1+param2);");
Closure will leave the String literals alone.
See https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function

What is the best way to organize JS code in webapps where the main "meat" is still server side?

When building webapps with MVC web framworks like Django, Kohana, Rails and the like, I put together the application without JS-driven components initially, and then add them afterwards as "improvements" to the UI.
This approach leads to non-intrusive JS, but I don't have a good "standard" way of how to go about organizing the JS work. Most of the JS I write in apps like these are 10-30 line JQuery snippets that hook into some very specific part of the UI.
So far I often end up inlining these things together with the part of the UI they manage. This makes me feel dirty, I'd like to keep the JS code as organized as the python / php / ruby code, I'd like for it to be testable and I'd like for it to be reusable.
What is the best way to go about organizing JS code in a setup like this, where we're not building a full-blown JS client app, and the main meat is still server side?
I am also very interested in what other people have to say about this. The approach I've taken is to use object literal notation to store the bulk of the function, and store these in one file included on all pages (the library)
uiHelper = {
inputDefault:function(defaulttext){
// function to swap default text into input elements
},
loadSubSection:function(url){
// loads new page using ajax instead of refreshing page
},
makeSortable:function(){
// apply jQuery UI sortable properties to list and remove non javascript controls
}
}
Then I include a .js file on any page that needs to use the library that ties the elements on that page to the function in the library. I've tried to make each function as reuseable as possible and sometimes the event binding function on the page calls several of my library functions.
$(document).ready(function(){
$('#mybutton').live('click',uiHelper.loadSubSection);
//more complicated helper
$('#myotherbutton').live('click',function(){
uiHelper.doThisThing;
uiHelper.andThisThing;
});
});
edit: using jsDoc http://jsdoc.sourceforge.net/ notation for commenting for these functions can produce documentation for the 'library' and helps keep your code easy to read (functions split by comments).
The following question is along similar lines to your own - you should check it out...
Commonly accepted best practices around code organization in JavaScript
When dealing with JS code, you should first analyze whether it will be used right away when the page loads. If it's not used right away (meaning the user must do something to invoke it) you should package this into a JS file and include it later so the load time is perceived faster for the user. This means that anything that the user will sees should go first and JS related to the functionality should be imported near the end of the file.
Download this tool to analyze your website: http://getfirebug.com/
If the JS code is small enough, it should just be inline with the HTML.
Hope that helps a bit.
For quick little user interface things like that I put everything into a single javascript file that I include on every page. Then in the javascript file I check what exists on the page and run code accordingly. I might have this in UIMagic.js for example. I have jQuery, so excuse those jQuery-isms if they aren't familiar to you.
function setupMenuHover() {
if ($("li.menu").length) { // The page has a menu
$("li.menu").hover(function() { ... }, function() { ... });
}
}
$(setupMenuHover);
function setupFacebookWizbang() {
if (typeof FB != "undefined") { // The page has Facebook's Javascript API
...
}
}
$(setupFacebookWizbang);
I've found this to be a sane enough approach.
My preferred method is to store inline javascript in it's own file (so that I can edit it easily with syntax highlighting etc.), and then include it on the page by loading the contents directly:
'<script type="text/javascript">'+open('~/js/page-inline.js').read()+'</script>'
This may not perform well though, unless your templating library can cache this sort of thing.
With Django you might be able to just include the js file:
<script type="text/javascript">
{% include "js/page-inline.js" %}
</script>
Not sure if that caches the output.
If you are still worried about being 'dirty', then you could check out the following projects, which try to bridge the server/client side language mismatch:
http://pyjs.org/ (Python generating JavaScript)
http://code.google.com/webtoolkit/ (Java generating JavaScript)
http://nodejs.org/ (JavaScript all the way!)

Client-side Javascript code to strip bogus HTML from CKEditor

I believe this may be related to Need Pure/jQuery Javascript Solution For Cleaning Word HTML From Text Area
But in my case I am using CKEditor; however, before sending the data to the server (or after receiving it back) I'd like to strip out "junk" HTML tags and comments such as those that appear when pasting from recent (2007 or later) versions of Microsoft Office. Because the server-side here is a third-party application, I'd prefer to do this client side if I can. Yes, I am aware of the security risks of doing that; this is just meant to sanitize data in common use cases.
Are there any common techniques or existing libraries (especially jQuery-friendly) that can do this? Note, I am not looking to encode or strip all HTML, only the Office-related crud.
Did you try CKEditor built in Word clean up functionality?
It seems to be run automatically when using the "Paste From Word" dialog, but can also be used from your code.
I'm not an expert on CKEditor API, so there might be a more efficient or correct way of doing this, but this seems to work on the current release (3.3.1):
function cleanUp() {
if (!CKEDITOR.cleanWord) {
// since the filter is lazily loaded by the pastefromword plugin we need to add it ourselves.
// We use the same function as the callback for when the cleanup filter is loaded. Change the script path to the correct one
CKEDITOR.scriptLoader.load("../plugins/pastefromword/filter/default.js", cleanUp, null, false, true );
alert('loading script for the first usage');
} else { // The cleanWord is available for use
// change to the correct editor instance
var editor = CKEDITOR.instances.editor1;
// perform the clean up
var cleanedUpData = CKEDITOR.cleanWord(editor .getData(), editor );
// do something with the clean up
alert(cleanedUpData);
}
}
cleanUp();
If you're not happy with this clean up you can modify default.js for your clean up needs.
There are some configuration options available for the cleanup, check http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html (search for "pasteFromWord" options).
If you need something more advanced, but that will require a server access, I suggest you check WordOff (http://wordoff.org/). You might be able to build a proxy and jsonp wrapper around their service so you can use it from the client without a server installation.

Categories

Resources