Is it possible to wrap all added js in a $(document).ready(function(){ as first line and }); as last line in cases using gulp-concat?
you can use gulp-concat-util for this
it does concat all files, and optionally add header line & footer line to concatenated text
var concat = require('gulp-concat-util');
gulp.task('concat:dist', function() {
gulp.src('scripts/{,*/}*.js')
.pipe(concat(pkg.name + '.js', {process: function(src) { return (src.trim() + '\n').replace(/(^|\n)[ \t]*('use strict'|"use strict");?\s*/g, '$1'); }}))
.pipe(concat.header('(function(window, document, undefined) {\n\'use strict\';\n'))
.pipe(concat.footer('\n})(window, document);\n'))
.pipe(gulp.dest('dist'));
});
I had the same question, and decided to hack something together. Maybe it will be helpful to you:
// remove jquery/use strict from independent files
// prior to concatenation, so all files are in the same context
function removeWrap( ) {
const readFileAsync = (filename) => {
return new Promise( (resolve) => {
fs.readFile('./src/js/' + filename, 'utf-8', function(err, content) {
let lines = content.split('\n')
lines.splice(0,2)
lines.splice(lines.length -2)
let newContent = lines.join('\n')
resolve( newContent)
})
})
}
fs.readdir('./src/js', function(err, filenames) {
filenames.forEach(function(filename) {
readFileAsync(filename).then( content => {
console.log( content[1] )
fs.writeFile('./src/js-temp/' + filename, content, ()=>{})
})
})
})
return Promise.resolve('the value is ignored');
}
// concat JS files
function concatFiles() {
return src('./src/js-temp/*.js')
.pipe(concat('main.js'))
.pipe(dest('./dist/js'));
}
function wrapMain() {
let header = `$(function() {
"use strict";\n`
let footer = `
});`
fs.readFile('./dist/js/main.js', 'utf-8', function(err, content) {
let newContent = header + content + footer
fs.writeFile('./dist/js/main.js', newContent, ()=>{})
})
return Promise.resolve('the value is ignored');
}
module.exports.devJs = series(removeWrap, concatFiles, wrapMain);
Related
In Outlook web add-in, I want to select text from email body, keep it as tracked object and then apply styling on it like we do in Word web add-in. In the Word, I do it the following way:
//used to store current selected range
var selection=null;
$scope.getSelectedText = function () {
Word.run(function (context) {
if (selection) {
context.trackedObjects.remove(selection);
}
selection = context.document.getSelection();
context.trackedObjects.add(selection);
context.load(selection, 'text');
return context.sync()
.then(function () {
if (!selection.text) {
systemService.errorHandler("Please select any text from the document");
return false;
}
}).then(context.sync);
})
.catch(systemService.errorHandler);
};
//highlight Words in the selected range or body
$scope.highlightWords = function (item) {
var color = systemService.getColor(item.gradeText);
var filteredWords = JSON.parse(localStorage.getItem("List")) || [];
var promise = new OfficeExtension.Promise(function (resolve, reject) { resolve(null); });
Word.run(function (context) {
var selectedRange = (selection) ? selection : context.document.body;
selectedRange.load('text');
return context.sync().then(function () {
if (selectedRange.text == "") {
systemService.showNotification("Alert:", "No text found in the document!");
return;
}
filteredWords.forEach(function (word) {
promise = promise.then(function () {
return highlightRange(word, color);
})
});
});
}).catch(function (error) {
console.log('Error: ' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
}
function highlightRange(word, color) {
return Word.run(selection, function (context) {
var range = (selection) ? selection : context.document.body;
var searchResults = null;
searchResults = range.search(word, { ignorePunct: true, matchCase: false, matchWholeWord: true });
searchResults.load('font');
return context.sync().then(function () {
for (var i = 0; i < searchResults.items.length; i++) {
searchResults.items[i].font.color = color;
searchResults.items[i].font.bold = true;
}
}).then(context.sync());
}).catch(function (error) {
console.log('Error: ' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
}
//highlight Words in the selected range or body
I have tried multiple ways to do but there is a problem while keeping track of the selected object. In Word, we can save the range and manipulate it overtime as needed, but in Outlook, the user have to keep the content selected in order to perform operation on it (like changing font color etc.). Also, do we have any font property available for outlook web add-ins like Word?
I'm using protractor html reporter 2 for my reporting. I need to get spec name as html report output file name.
i'm using the below code in my config file.
var today = new Date(),
timeStamp = today.getMonth() + 1 + '-' + today.getDate() + '-' + today.getFullYear();
onPrepare:
function ()
{
browser.driver.manage().window().maximize();
var fs = require('fs-extra');
scriptName=function(){
return browser.getProcessedConfig().then(function(config){
return config.specs;
});
};
fs.emptyDir('./target/htmlReports/'+scriptName+'-'+timeStamp+'/screenShots/', function (err) {
console.log(err);
});
jasmine.getEnv().addReporter({
specDone: function(result) {
//if (result.status == 'failed' || result.status == 'passed') {
if (1==1) {
browser.getCapabilities().then(function (caps) {
var browserName = userData.testUser.browser.toUpperCase();
browser.takeScreenshot().then(function (png) {
var stream = fs.createWriteStream('./target/htmlReports/'+scriptName+'-'+timeStamp+'/screenShots/'+ result.fullName+'.png');
stream.write(new Buffer(png, 'base64'));
stream.end();
});
});
}
}
});
jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
consolidateAll: true,
savePath: 'target/XMLReports',
filePrefix: 'xmlresults'
}));
},
onComplete: function() {
var browserName, browserVersion;
var capsPromise = browser.getCapabilities();
capsPromise.then(function (caps) {
browserName = userData.testUser.browser.toUpperCase();
platform=caps.get('platform');
browserVersion = caps.get('version');
testConfig = {
reportTitle: 'Test Execution Report',
outputPath: './target/htmlReports/'+scriptName+'-'+timeStamp,
screenshotPath: './target/htmlReports/'+scriptName+'-'+timeStamp+'/screenShots',
testBrowser: browserName,
browserVersion: browserVersion,
outputFilename:'ProtractorTestReport',
testPlatform: platform,
//browserVersion: browserVersion,
modifiedSuiteName: true,
screenshotsOnlyOnFailure: false
};
new HTMLReport().from('./target/XMLReports/xmlresults.xml', testConfig);
});
},
plugins: [{
package: 'jasmine2-protractor-utils',
disableHTMLReport: true,
disableScreenshot: false,
screenshotPath:'./target/htmlReports/'+scriptName+'-'+timeStamp+'/screenShots',
screenshotOnExpectFailure:true,
screenshotOnSpecFailure:true,
clearFoldersBeforeTest: true,
htmlReportDir: './target/htmlReports'
}],
i tried with
browser.getProcessedConfig().then(function(config){
console.log(config.specs);
});
,it returns
[ 'D:\projects\HeartlandSSP\Automation\TenantManagement\Ssp.TenantManagement.Protractor_Test\specs\createTenantSpec.js',
'C:\Users\renusri.rajalingam\AppData\Roaming\npm\node_modules\protractor\built\frameworks\__protractor_internal_afterEach_setup_spec.js' ]
but the actual spec name createTenantSpec.js is not returning. I need only the filename of the spec and not the name of the describe or it functions. Since I have 5 specs, i need to generate separate report with its spec name. Can anyone please help me on this?
The value of config.specs is an array and according to output we have the file's absolute path is at index 0. So the file name can be extracted as follows.
browser.getProcessedConfig().then(function (config) {
var fullName = config.specs[0];
var fileName = fullName.substring(fullName.lastIndexOf('/')+1);
console.log('fileName:', fileName);
});
// output:
// fileName: createTenantSpec.js
Or if you would like to have all file names in this array you could use this:
browser.getProcessedConfig().then(function (config) {
var fileNames = config.specs.map(function(path) {
return path.substring(path.lastIndexOf('/')+1);
});
fileNames.forEach(function(fileName) {
console.log('fileName:', fileName);
});
});
// output:
// fileName: createTenantSpec.js
// __protractor_internal_afterEach_setup_spec.js
References:
array.prototype.map() => click me
array.prototype.forEach() => click me
Use this in on Complete:
browser.getProcessedConfig().then(function (config)
{
var fullName = config.specs[0];
console.log('fullName' ,fullName);
var start= fullName.lastIndexOf('\\');
var stop=fullName.length;
console.log('start:', start);
console.log('stop:', stop);
var fileName = fullName.substring(start+1,stop);
console.log('fileName:', fileName);
});
I am trying to accomplish this:
I have a spell checker in the middleware. In case the user's input text does not match the corrected text, I would like to confirm the corrected text with the user before proceeding. I tried several approaches but have not been able to achieve this. Here's the code I wrote:
app.js:
var builder = require('botbuilder');
var restify = require('restify');
var spellService = require('./spell-service')
// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});
// Create connector and listen for messages
var connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
server.post('/api/messages', connector.listen());
var bot = new builder.UniversalBot(connector, function (session) {
session.beginDialog('search');
});
bot.dialog('search', [
function (session, args, next) {
builder.Prompts.text(session, 'Type the name of a company you would like to search');
}
]);
//=========================================================
// Spell checker
//=========================================================
const dontCorrectIdentifier = "dontCorrect";
bot.use({
botbuilder: function (session, next) {
if (session.message.text.startsWith(dontCorrectIdentifier)) {
session.message.text = session.message.text.replace(dontCorrectIdentifier, "");
next();
} else {
spellService
.getCorrectedText(session.message.text)
.then(function (text) {
if (session.message.text !== text) {
var msg = new builder.Message(session)
.text("Did you mean \"" + text + "\"?")
.suggestedActions(builder.SuggestedActions.create(session, [
builder.CardAction.postBack(session, dontCorrectIdentifier + text, "Yes"),
builder.CardAction.postBack(session, dontCorrectIdentifier + session.message.text, "No")
]
));
builder.Prompts.text(session, msg);
}
next();
})
.catch(function (error) {
console.error(error);
next();
});
}
}
});
spell-service.js
// from https://dev.cognitive.microsoft.com/docs/services/56e73033cf5ff80c2008c679/operations/56e73036cf5ff81048ee6727
var request = require('request');
var SPELL_CHECK_API_URL = 'https://api.cognitive.microsoft.com/bing/v7.0/SpellCheck?mkt=en-US&mode=proof',
SPELL_CHECK_API_KEY = 'MY KEY';
/**
* Gets the correct spelling for the given text
* #param {string} text The text to be corrected
* #returns {Promise} Promise with corrected text if succeeded, error otherwise.
*/
exports.getCorrectedText = function (text) {
return new Promise(function (resolve, reject) {
if (text) {
var requestData = {
url: SPELL_CHECK_API_URL,
headers: {
"Ocp-Apim-Subscription-Key": SPELL_CHECK_API_KEY
},
form: {
text: text
},
json: true
};
request.post(requestData, function (error, response, body) {
if (error) {
reject(error);
} else if (response.statusCode != 200) {
reject(body);
} else {
var previousOffset = 0;
var result = '';
for (var i = 0; i < body.flaggedTokens.length; i++) {
var element = body.flaggedTokens[i];
// append the text from the previous offset to the current misspelled word offset
result += text.substring(previousOffset, element.offset);
// append the first suggested correction instead of the misspelled word
result += element.suggestions[0].suggestion;
// Increment the offset by the length of the misspelled word
previousOffset = element.offset + element.token.length;
}
// Append the text after the last misspelled word.
if (previousOffset < text.length) {
result += text.substring(previousOffset);
}
resolve(result);
}
});
} else {
resolve(text);
}
})
};
Based on Gary's suggestion, here's the right way to do this:
bot.use({
botbuilder: function (session, next) {
if (session.message.text.startsWith(dontCorrectIdentifier)) {
session.message.text = session.message.text.replace(dontCorrectIdentifier, "");
next();
} else {
spellService
.getCorrectedText(session.message.text)
.then(function (text) {
if (session.message.text !== text) {
var msg = new builder.Message(session)
.text("Did you mean \"" + text + "\"?")
.suggestedActions(builder.SuggestedActions.create(session, [
builder.CardAction.postBack(session, dontCorrectIdentifier + text, "Yes"),
builder.CardAction.postBack(session, dontCorrectIdentifier + session.message.text, "No")
]
));
session.send(msg);
} else {
next();
}
})
.catch(function (error) {
console.error(error);
next();
});
}
}
});
Modify the logic flow in the builder middle, which works fine on my side:
bot.use({
botbuilder: (session, next) => {
if (session.message.text.startsWith(dontCorrectIdentifier)) {
session.message.text = session.message.text.replace(dontCorrectIdentifier, "");
next();
} else {
var text = session.message.text;
var msg = new builder.Message(session)
.text("Did you mean \"" + text + "\"?")
.suggestedActions(builder.SuggestedActions.create(session, [
builder.CardAction.postBack(session, dontCorrectIdentifier + text, "Yes"),
builder.CardAction.postBack(session, dontCorrectIdentifier + session.message.text, "No")
]));
session.send(msg);
}
},
})
Use session.send(msg); replace builder.Prompts.text(session, msg).
And remove next() in the else condition.
You need to append text parameter in URL. I tried this in curl:
curl -v -X GET https://api.cognitive.microsoft.com/bing/v7.0/SpellCheck?mkt=en-US&mode=proof&text=hollo%2Cwrld
The other thing is hyphen between spell and service in your .js file. You can probably try to check json response first to see if you are getting correction back.
I'm trying to use promise to get in promise2
But if I have an object Widgets with several elements in it...
Why can't I have been able to get my console.log's output
Parse.Cloud.define("extract", function(request, response) {
var user = request.params.user;
var promise = Parse.Promise.as();
[...]
}).then(function() {
return query.find().then(function(results) {
_.each(results, function(result) {
[...]
Widget.objectId = result.id;
Widgets[timestamp] = Widget;
});
return promise;
}).then(function(results) {
for (var key in Widgets) {
var Widget = Widgets[key];
var widget_data = Widgets[key].widget_data;
var promise2 = Parse.Promise.as();
promise2 = promise2.then(function() {
return Parse.Cloud.run('extractWidgetData', {
'widget_data': widget_data,
}).then(function(newresult) {
Widgets[key].data = newresult.data;
console.log('--------WHY NOT HERE ALL TIME ?--------');
});
});
return promise2;
}
}).then(function() {
response.success(Widgets);
},
function(error) {
response.error("Error: " + error.code + " " + error.message);
});
});
});
I'm becoming crazy to run this damn Code
EDIT : I finally followed Roamer's advices to implement something but I'm not sure if it's the good way to work with Promise in series...
Parse.Cloud.define("extract", function(request, response) {
var user = request.params.user;
var Widgets = {};
...
... .then(function() {
return query.find().then(function(results) {
return Parse.Promise.when(results.map(function(result) {
var Widget = ...;//some transform of `result`
Widget.id = ...;//some transform of `result`
var timestamp = createdAtDate.getTime();
...
return Parse.Cloud.run('extractData', {
'widget_data': Widget.widget_data,
}).then(function(newresult) {
Widget.stat = newresult.stats;
return Widget;//<<<<<<< important! This ensures that results.map() returns an array of promises, each of which delivers a Widget objects.
});
}));
}).then(function() {
var promisedWidget = Array.prototype.slice.apply(arguments);
return Parse.Promise.when(promisedWidget.map(function(Widget) {
return Parse.Cloud.run('getWineStats', {
'id': Widget.data.id
}).then(function(stat) {
Widget.stat = stat;
return Widget;
});
}));
}).then(function() {
var promisedWidget = Array.prototype.slice.apply(arguments);
_.each(promisedWidget, function(Widget) {
var createdAtObject = Widget.createdAt;
var strDate = createdAtObject.toString();
var createdAtDate = new Date(strDate);
timestamp = createdAtDate.getTime();
Widgets[timestamp] = Widget;
});
return Widgets;
}).then(function(Widgets) {
response.success(Widgets);
},
function(error) {
response.error("Error: " + error.code + " " + error.message);
});
});
});
First, I echo Bergi's comment on indentation/matching parenthesis.
But ignoring that for a moment, at the heart of the code you have return query.find().then(...).then(...).then(...) but the flow from the first .then() to the second is incorrect. Besides which, only two .then()s are necessary as the code in the first then is synchronous, so can be merged with the second.
Delete the two lines above for (var key in Widgets) { then at least Widgets will be available to be processed further.
Going slightly further, you should be able to do all the required processing of results in a single loop. There seems to be little pont in building Widgets with _.each(...) then looping through the resulting object with for (var key in Widgets) {...}.
In the single loop, you probably want a Parse.Promise.when(results.map(...)) pattern, each turn of the map returning a promise of a Widget. This way, you are passing the required data down the promise chain rather than building a Widgets object in an outer scope.
Do all this and you will end up with something like this :
Parse.Cloud.define("extract", function(request, response) {
var user = request.params.user;
...
... .then(function() {
return query.find().then(function(results) {
return Parse.Promise.when(results.map(function(result) {
var Widget = ...;//some transform of `result`
...
return Parse.Cloud.run('extractWidgetData', {
'widget_data': Widget.widget_data,
}).then(function(newresult) {
Widget.data = newresult.data;
return Widget;//<<<<<<< important! This ensures that results.map() returns an array of promises, each of which delivers a Widget objects.
});
}));
}).then(function() {
//Here, compose the required Widgets array from this function's arguments
var Widgets = Array.prototype.slice.apply(arguments);//Yay, we got Widgets
response.success(Widgets);
}, function(error) {
response.error("Error: " + error.code + " " + error.message);
});
});
});
I was wondering how to convert Variable-length binary data(255216255224016747073700110010100255) to a jpeg or png to the web browser?
Example Code:
var Connection = require('tedious').Connection;
var config = {
"userName": "user#server.database.windows.net",
"password": "pswd",
"server": "server.database.windows.net",
"options": {
"database": "db",
"encrypt": true,
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
console.log("Connected");
}
);
var Request = require('tedious').Request;
var result,
resG;
function sendResponse() {
var vals;
// Convert to string then array
var resultA = result.toString().split(',');
// Now I can loop through the data returned
resultA.forEach(function(val, index, ar) {
if(vals == null) {
vals = val;
} else {
vals += val;
}
});
resG.writeHead(200, {'Content-Type': 'text/html', 'Content-Length': vals.length});
//console.log(vals);
//resG.end("<img src=\"data:image/jpg;base64," + vals + "\" />");
// Output data returned from db as string
resG.end("" + vals);
}
function executeStatement() {
request = new Request("SELECT Photos FROM dbo.tbl WHERE FarmerFirstName='someName' AND FarmerLastName='someLastName'", function(err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
});
request.on('row', function(columns) {
columns.forEach(function(column) {
result = column.value;
});
});
request.on('doneInProc', function(rowCount, more) {
// Got everything needed from db move on to sending a response
sendResponse();
});
connection.execSql(request);
}
var http = require('http'),
director = require('director');
var router = new director.http.Router({
"/": {
get: executeStatement
}
});
var server = http.createServer(function (req, res) {
// set global res var
resG = res;
router.dispatch(req, res, function (err) {
if (err) {
res.writeHead(404);
res.end();
}
});
});
server.listen(80);
I'm using tedious for my db connector and director as my router.
The result is already an array of bytes for the Image. You do not need to do any fancy transformations on it. This should work.
function sendResponse() {
resG.writeHead(200, {'Content-Type': 'image/jpeg', 'Content-Length': result.length});
resG.end(new Buffer(result));
}
or if you want to serve it as part of an HTML page, this:
function sendResponse() {
resG.writeHead(200, {'Content-Type': 'text/html'});
var vals = (new Buffer(result)).toString('base64')
resG.end("<html><body>" +
"<img src=\"data:image/jpg;base64," + vals + "\" />" +
"</body></html>");
}