Caching content of Virtual Documents - visual-studio-code

I made my TextDocumentContentProvider for virtual documents. I'm generating the content of the file on the go, and it looks like VS Code is caching the content of the file. This is a problem for me. I expect to see a new number in the text of the document every time. Does anyone know how to get around this without using random numbers in the filename?
const vscode = require('vscode');
class MyVirtualDocument {
constructor() {
this.onDidChangeEmitter = new vscode.EventEmitter();
this.onDidChange = this.onDidChangeEmitter.event;
}
provideTextDocumentContent(uri) {
return "Test String for uri: " + uri.path + "\nRandom number: " + Math.floor(Math.random() * 65535) + ".";
}
};
function activate(context)
{
context.subscriptions.push(vscode.workspace.registerTextDocumentContentProvider('myvirtualdocument', new MyVirtualDocument()));
context.subscriptions.push(vscode.commands.registerCommand('myvirtualdocument.open', () => {
vscode.workspace.openTextDocument(vscode.Uri.parse('myvirtualdocument:1.txt')).then(doc => {
vscode.window.showTextDocument(doc, { preview: true });
});
}));
}
function deactivate(){}
module.exports = {activate, deactivate}

Related

Unable to retrieve WP post feature image url through JSON

was looking for a way to get the post featured image but it doesn't seem to output the data using {{ post._embedded['wp:featuredmedia'].link }} although _embed was used. Was wondering if there is anything wrong with my code and that someone could guide me out?
export class WordPressRestapiService {
baseRestApiUrl: string = this.appConfig.Shop_URL + '/wp-json/wp/v2/';
constructor(private httpClient: HttpClient, public appConfig: AppConfig) { }
getRecentPosts(categoryId: number, page: number = 1): Observable<Post[]> {
// Get posts by a category if a category id is passed
let category_url = categoryId ? ("&categories=" + categoryId) : "";
return this.httpClient.get(this.baseRestApiUrl + "posts?_embed&page=" + page + category_url ).pipe(
map((posts: Post[]) => {
return posts.map((post) => new Post(post));
}),
catchError(error => {
return Observable.throw('Something went wrong ;)');
})
);
}
getPost(postId: number): Observable<Post> {
return this.httpClient.get(this.baseRestApiUrl + "posts/" + postId + "?_embed").pipe(
map(post => {
return new Post(post);
}),
catchError(error => {
return Observable.throw('Something went wrong ;)');
})
);
}
}
to get post feature image , if your json called " post" , in .html file use
<img src="{{post?._embedded['wp:featuredmedia'][0]?.media_details.sizes.full.source_url}}">

With Chrome FileSystem, let the user choose a Directory, load files inside. And save files in that directory without prompting again

I could not found any examples with this scenario so here we go:
I want the user choose a directory, load all files inside it, change them, and save this file overriding it or saving a new file in that same directory without asking where he want to save.
I don't know how to list the files of the directory
I don't know how to save a file in a directory without prompting the filechooser window
I believe it is possible because I see something similar here (last paragraph):
http://www.developer.com/lang/using-the-file-api-outside-the-sandbox-in-chrome-packaged-apps.html
Any answer will be appreciated, Thank you
EDIT: Thanks to Chris Johnsen for giving me this great answer:
var fileHandler = function() {
var _entry = null;
this.open = function(cb) {
chrome.fileSystem.chooseEntry({
type: 'openDirectory'
}, function(dirEntry) {
if (!dirEntry || !dirEntry.isDirectory) {
cb && cb(null);
return;
}
_entry = dirEntry;
listDir(_entry, cb);
});
};
this.save = function(filename, source) {
chrome.fileSystem.getWritableEntry(_entry, function(entry) {
entry.getFile(filename, {
create: true
}, function(entry) {
entry.createWriter(function(writer) {
writer.onwrite = function() {
writer.onwrite = null;
writer.truncate(writer.position);
};
writer.write(new Blob([source], {
type: 'text/javascript'
}));
});
});
});
};
this.saveAs = function(filename, source) {
chrome.fileSystem.chooseEntry({
type: 'openDirectory'
}, function(entry) {
chrome.fileSystem.getWritableEntry(entry, function(entry) {
entry.getFile(filename, {
create: true
}, function(entry) {
entry.createWriter(function(writer) {
writer.onwrite = function() {
writer.onwrite = null;
writer.truncate(writer.position);
};
writer.write(new Blob([source], {
type: 'text/javascript'
}));
});
});
});
});
};
var listDir = function(dirent, cb, listing) {
if (listing === undefined) {
listing = [];
}
var reader = dirent.createReader();
var read_some = reader.readEntries.bind(reader, function(ents) {
if (ents.length === 0) {
return cb && cb(listing);
}
var process_some = function(ents, i) {
for (; i < ents.length; i++) {
listing.push(ents[i]);
if (ents[i].isDirectory) {
return listDir(ents[i], process_some.bind(null, ents, i + 1), listing);
}
}
read_some();
};
process_some(ents, 0);
}, function() {
console.error('error reading directory');
});
read_some();
};
};
Your save method should work fine (mostly, see below) for your second requirement (write to a code-chosen filename without another user prompt), but there are a couple of bugs in open (at least as presented in the question):
Inside the chooseEntry callback, this !== fileHandler because the callback is invoked with a different this (probably the background page’s window object).
You can work around this in several ways:
Use fileHandler instead of this (if you are not using it as any kind of prototype).
Use .bind(this) to bind each of your callback functions to the same context.
Use var self = this; at the top of open and use self.entry (et cetera) in the callbacks.
You may want to call cb for the success case. Maybe you have another way of postponing calls to (e.g.) fileHandler.save (clicking on some element to trigger the save?), but adding something like
⋮
cb && cb(self.entry);
⋮
after self.entry = dirEntry makes it easy to (e.g.) chain open and save:
fileHandler.open(function(ent) {
fileHandler.save('newfile','This is the text\nto save in the (possibly) new file.');
});
There is a latent bug in save: if you ever overwrite an existing file, then you will want to call writer.truncate() (unless you always write more bytes than the file originally held).
⋮
writer.onwrite = function() {
writer.onwrite = null;
writer.truncate(writer.position);
};
writer.write(…);
⋮
It looks like you have a good start on the file listing part. If you want to reference the list of files later, then you might want to save them in your object instead of just logging them; this can get a bit hairy if you want to recurse into subdirectories (and also not assume that readEntries returns everything for its first call).
function list_dir(dirent, cb, listing) {
if (listing === undefined) listing = [];
var reader = dirent.createReader();
var read_some = reader.readEntries.bind(reader, function(ents) {
if (ents.length === 0)
return cb && cb(listing);
process_some(ents, 0);
function process_some(ents, i) {
for(; i < ents.length; i++) {
listing.push(ents[i]);
if (ents[i].isDirectory)
return list_dir(ents[i], process_some.bind(null, ents, i + 1), listing);
}
read_some();
}
}, function() {
console.error('error reading directory');
});
read_some();
}
You could use it in the open callback (assuming you add its success callback) like this:
fileHandler.open(function(ent) {
ent && list_dir(ent, function(listing) {
fileHandler.listing = listing;
console.log('listing', fileHandler.listing.map(function(ent){return ent.fullPath}).join('\n'));
fileHandler.save('a_dir/somefile','This is some data.');
});
});

Creating new Meteor collections on the fly

Is it possible to create new Meteor collections on-the-fly? I'd like to create foo_bar or bar_bar depending on some pathname which should be a global variable I suppose (so I can access it throughout my whole application).
Something like:
var prefix = window.location.pathname.replace(/^\/([^\/]*).*$/, '$1');
var Bar = new Meteor.Collection(prefix+'_bar');
The thing here is that I should get my prefix variable from URL, so if i declare it outside of if (Meteor.isClient) I get an error: ReferenceError: window is not defined. Is it possible to do something like that at all?
Edit : Using the first iteration of Akshats answer my project js : http://pastie.org/6411287
I'm not entirely certain this will work:
You need it in two pieces, the first to load collections you've set up before (on both the client and server)
var collections = {};
var mysettings = new Meteor.Collection('settings') //use your settings
//Startup
Collectionlist = mysettings.find({type:'collection'});
Collectionlist.forEach(function(doc) {
collections[doc.name] = new Meteor.Collection(doc.name);
})'
And you need a bit to add the collections on the server:
Meteor.methods({
'create_server_col' : function(collectionname) {
mysettings.insert({type:'collection', name: collectionname});
newcollections[collectionname] = new Collection(collectionname);
return true;
}
});
And you need to create them on the client:
//Create the collection:
Meteor.call('create_server_col', 'My New Collection Name', function(err,result) {
if(result) {
alert("Collection made");
}
else
{
console.log(err);
}
}
Again, this is all untested so I'm just giving it a shot hopefully it works.
EDIT
Perhaps the below should work, I've added a couple of checks to see if the collection exists first. Please could you run meteor reset before you use it to sort bugs from the code above:
var collections = {};
var mysettings = new Meteor.Collection('settings')
if (Meteor.isClient) {
Meteor.startup(function() {
Collectionlist = mysettings.find({type:'collection'});
Collectionlist.forEach(function(doc) {
eval("var "+doc.name+" = new Meteor.Collection("+doc.name+"));
});
});
Template.hello.greeting = function () {
return "Welcome to testColl.";
};
var collectionname=prompt("Enter a collection name to create:","collection name")
create_collection(collectionname);
function create_collection(name) {
Meteor.call('create_server_col', 'tempcoll', function(err,result) {
if(!err) {
if(result) {
//make sure name is safe
eval("var "+name+" = new Meteor.Collection('"+name+"'));
alert("Collection made");
console.log(result);
console.log(collections);
} else {
alert("This collection already exists");
}
}
else
{
alert("Error see console");
console.log(err);
}
});
}
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
Collectionlist = mysettings.find({type:'collection'});
Collectionlist.forEach(function(doc) {
collections[doc.name] = new Meteor.Collection(doc.name);
});
});
Meteor.methods({
'create_server_col' : function(collectionname) {
if(!mysettings.findOne({type:'collection', name: collectionname})) {
mysettings.insert({type:'collection', name: collectionname});
collections[collectionname] = new Meteor.Collection(collectionname);
return true;
}
else
{
return false; //Collection already exists
}
}
});
}
Also make sure your names are javascript escaped.
Things got much easier:
var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
db.createCollection("COLLECTION_NAME", (err, res) => {
console.log(res);
});
Run this in your server method.

jQuery select2 genemuFormBundle issue

I am trying to implement ajax call using select2 as per this example:
https://github.com/genemu/GenemuFormBundle/blob/master/Resources/doc/jquery/select2/ajax.md
Here is my code:
var $configs = {{ configs|json_encode|raw }};
$field = $('#{{ id }}');
$configs = $.extend($configs, {
ajax: {
id: function (friend) { return friend.username; },
url: $field.data('url'),
data: function (term, page) {
return { q: term, page_limit: 10, page: page };
},
results: function (data, page) {
var more = (page * 10) < data.total;
return { results: data, more: more };
}
},
formatResult: function (friend) {
var markup = "<div class='friend-results-box'>";
if (friend.avatar !== undefined) {
markup += "<img width='60' height='75' src='" + friend.avatar + "'/>";
}
markup += "<h5>" + friend.username + "</h5>";
markup += "<div class'clearfix'></div>";
markup += "</div>";
return markup;
},
initSelection : function (element, callback) {
var elementText = $(element).attr('data-init-text'); // ?
callback({"term":elementText});
},
formatSelection: function (friend) { return friend.username; },
escapeMarkup: function (m) { return m; },
dropdownCssClass: "dropdown-friends"
});
$field.select2($configs);
Now my issues are:
Value is being filled in with ID when my intention is to have a
value taken from json defined there as friend.username
After page reload initial value is not being presented on the screen
(as value is being set to ID) and select2 does not pick it up
Any tips or help would be much appreciated!
Your initSelection function has this: callback({"term":elementText});
by default Select2 expects {id:"someid", text:"sometext"}
Best to start simple with no formatting of any kind, get that working then make it look like you want.

Is there a nodejs module or example of how to make GridFS files accessible with WebDAV?

I have an existing node.js app where users have a library of files that are stored with GridFS. Each user has their own library. I would like to make the library mountable with WebDAV so that a user could manage their library from their desktop.
I have seen jsDAV used to access the filesystem but it is not clear how to extend it for use with a virtual file system. I found gitDav but it is not clear how to use it.
Is this even possible without starting from scratch?
I was looking to use jsDAV to make some resources available through WebDAV. Failing to find a working example, I studied the comments in the source and wrote one myself. jsDAV is a port from a PHP library. The Sabre manual is useful guide in general. One thing to remember is that since we're in an asynchronous environment, functions that return the results in PHP might have to invoke a callback function instead. This usually happens when the operation in question involves reading from the disk. The first parameter to the callback will always be an error object, which should be null when all goes well.
'use strict';
var crypto = require('crypto');
var jsDAV = require("jsDAV/lib/jsdav");
var jsDAVLocksBackendFS = require("jsDAV/lib/DAV/plugins/locks/fs");
var jsDAVFile = require("jsDAV/lib/DAV/file");
var jsDAVCollection = require("jsDAV/lib/DAV/collection");
var jsExceptions = require("jsDAV/lib/shared/exceptions");
var VirtualFile = jsDAVFile.extend(
{
initialize: function(name, buffer) {
this.name = name;
this.buffer = buffer;
},
getName: function() {
return this.name;
},
get: function(callback) {
callback(null, this.buffer);
},
put: function(data, type, callback) {
callback(new jsExceptions.Forbidden("Permission denied to change data"));
},
getSize: function(callback) {
callback(null, this.buffer.length);
},
getETag: function(callback) {
var shasum = crypto.createHash('sha1');
shasum.update(this.buffer);
var etag = '"' + shasum.digest('hex') + '"';
callback(null, etag);
},
getContentType: function(callback) {
callback(null, 'text/plain');
}
});
var VirtualDirectory = jsDAVCollection.extend(
{
initialize: function(name, children) {
this.name = name;
this.children = children;
},
getChildren: function(callback) {
var list = [];
for (var name in this.children) {
list.push(this.children[name]);
}
callback(null, list);
},
getChild: function(name, callback) {
var child = this.children[name];
if (child) {
callback(null, child);
} else {
callback(new jsExceptions.NotFound("File not found"));
}
},
childExists: function(name, callback) {
var exists = (this.children[name] !== undefined);
callback(null, exists);
},
getName: function() {
return this.name;
}
});
var children = {};
for (var i = 1; i <= 10; i++) {
var name = 'file' + i + '.txt';
var text = 'Hello world, #' + i;
children[name] = VirtualFile.new(name, new Buffer(text, 'utf8'));
}
var grandchildren = {};
for (var i = 66; i <= 99; i++) {
var name = 'beer' + i + '.txt';
var text = i + ' bottles of beer';
grandchildren[name] = VirtualFile.new(name, new Buffer(text, 'utf8'));
}
children['folder'] = VirtualDirectory.new('folder', grandchildren);
var root = VirtualDirectory.new(null, children);
var options = {
node: root,
locksBackend: jsDAVLocksBackendFS.new(__dirname + "/data")
};
var port = 8000;
jsDAV.createServer(options, port);
It looks like jsDAV is the only option. It is a port of a PHP library and it is not setup in such a way that you can use it like a normal node.js module. I found a few examples of server types that others have created to connect it with dropbox and couchdb.
I am now working on a server type that will work more like you would expect a node.js module to work. The next step will be making it play nice with npm. You can see my fork here.