Why is babeljs.io output different than gulp-babel output? - ecmascript-6

Background
I am trying to transpile my ES6 js to ES5 js. When I visit the https://babeljs.io/repl webpage to test out what babel should output for the preset option es2015 it outputs JavaScript that is different than what gulp-babel outputs.
Input ES6 JavaScript
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k" https://stackoverflow.com/a/9461657
const round = num => (num > 999 ? `${(num / 1000).toFixed(1)}k` : num);
// Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(async (a) => {
const link = a;
const name = link.getAttribute('href').split('/').slice(-2).join('/');
const url = `https://api.github.com/repos/${name}`;
const { starGazersCount } = await fetch(url).then(res => res.json());
if (!starGazersCount) return;
link.querySelector('.stars').innerText = `${'⭐️ '}${round(starGazersCount)}`;
});
}
babeljs.io output ~Desired Output~
'use strict';
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k" https://stackoverflow.com/a/9461657
var round = function round(num) {
return num > 999 ? (num / 1000).toFixed(1) + 'k' : num;
};
// Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(async function (a) {
var link = a;
var name = link.getAttribute('href').split('/').slice(-2).join('/');
var url = 'https://api.github.com/repos/' + name;
var _ref = await fetch(url).then(function (res) {
return res.json();
}),
starGazersCount = _ref.starGazersCount;
if (!starGazersCount) return;
link.querySelector('.stars').innerText = '⭐️ ' + round(starGazersCount);
});
}
gulp-babel output
"use strict";
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
(function () {
function r(e, n, t) {
function o(i, f) {
if (!n[i]) {
if (!e[i]) {
var c = "function" == typeof require && require;
if (!f && c) return c(i, !0);
if (u) return u(i, !0);
var a = new Error("Cannot find module '" + i + "'");
throw a.code = "MODULE_NOT_FOUND", a;
}
var p = n[i] = {
exports: {}
};
e[i][0].call(p.exports, function (r) {
var n = e[i][1][r];
return o(n || r);
}, p, p.exports, r, e, n, t);
}
return n[i].exports;
}
for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) {
o(t[i]);
}
return o;
}
return r;
})()({
1: [function (require, module, exports) {
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k" https://stackoverflow.com/a/9461657
var round = function round(num) {
return num > 999 ? "".concat((num / 1000).toFixed(1), "k") : num;
}; // Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(
/*#__PURE__*/
function () {
var _ref = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(a) {
var link, name, url, _ref2, starGazersCount;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
link = a;
name = link.getAttribute('href').split('/').slice(-2).join('/');
url = "https://api.github.com/repos/".concat(name);
_context.next = 5;
return fetch(url).then(function (res) {
return res.json();
});
case 5:
_ref2 = _context.sent;
starGazersCount = _ref2.starGazersCount;
if (starGazersCount) {
_context.next = 9;
break;
}
return _context.abrupt("return");
case 9:
link.querySelector('.stars').innerText = '⭐️ '.concat(round(starGazersCount));
case 10:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}());
}
}, {}]
}, {}, [1]);
⚠️Notice how the gulp-babel output contains polyfill functions such as _asyncToGenerator & asyncGeneratorStep.
Why does the online babel editor not output this when using the es2015 preset?
Other Useful files
Below is my .babelrc:
{
"presets": [
"#babel/preset-env"
]
}
Below is my package.json:
{
"devDependencies": {
"#babel/core": "^7.0.0",
"#babel/preset-env": "^7.0.0",
"babel-eslint": "^10.0.1",
"babel-preset-env": "^1.7.0",
"bower": "^1.8.2",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"gulp-babel": "^8.0.0",
"gulp-changed": "^3.2.0",
"gulp-cssnano": "^2.1.2",
"gulp-error-handle": "^1.0.0",
"gulp-eslint": "^5.0.0",
"gulp-gh-pages": "^0.5.4",
"gulp-htmlmin": "^5.0.1",
"gulp-imagemin": "^5.0.3",
"gulp-include": "^2.3.1",
"gulp-notify": "^3.2.0",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^8.0.0",
"gulp-pug": "^4.0.1",
"gulp-rename": "^1.2.2",
"gulp-sass": "*",
"gulp-size": "^3.0.0",
"gulp-sourcemaps": "^2.6.*",
"gulp-strip-css-comments": "^2.0.0",
"gulp-strip-debug": "^3.0.0",
"gulp-surge": "^0.1.0",
"gulp-terser": "^1.1.5",
"gulp-util": "^3.0.8",
"localtunnel": "^1.8.3",
"main-bower-files": "^2.13.1",
"path": "^0.12.7",
"postcss-cli": "^6.0.1",
"run-sequence": "^2.2.1",
"yarn": "^1.12.3"
},
"dependencies": {
"animate.css": "latest",
"argv": "^0.0.2",
"autoprefixer": "^9.3.1",
"babel-polyfill": "^6.26.0",
"browser-sync": "^2.18.13",
"browserify": "^16.2.3",
"bulma": "latest",
"del": "^3.0.0",
"gulp": "^3.9.1",
"gulp-load-plugins": "^1.5.0",
"hamburgers": "latest",
"hover": "latest",
"imagemin-pngquant": "^6.0.0",
"isinviewport": "latest",
"jquery": "latest",
"lost": "^8.2.0",
"minimist": "^1.2.0",
"moment": "^2.22.2",
"node-bourbon": "^4.2.8",
"node-neat": "^2.0.0-beta.0",
"psi": "^3.1.0",
"require-dir": "^1.1.0",
"rucksack-css": "^1.0.2",
"vanilla-lazyload": "latest",
"vinyl-buffer": "^1.0.1",
"vinyl-ftp": "^0.6.0",
"vinyl-source-stream": "^2.0.0"
}
}
Below is my js task for gulp:
'use-strict';
const gulp = require('gulp');
const $ = require('gulp-load-plugins')({ lazy: true });
const browserify = require('browserify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const paths = require('../../paths.js');
const config = require('../../config.js')();
gulp.task('eslint', () => {
console.log('-> Running eslint');
// Select files
gulp.src(`${paths.to.js.in}/**/*.js`)
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Check for lint errors
.pipe($.eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe($.eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe($.eslint.failAfterError());
});
gulp.task('js', ['eslint'], () => {
const env = ((config.environment || process.env.NODE_ENV || 'development').trim().toLowerCase() !== 'production');
console.log(`-> Compiling JavaScript for ${config.environment}`);
// Obtain a readable stream containing the processed browserified bundle
const bundle = browserify({
entries: paths.to.js.in,
debug: env,
})
.bundle()
// Convert browserify stream to a gulp-readable steam & buffer
.pipe(source(config.js.name))
.pipe(buffer());
if (env) {
// Select bundle
bundle
// Initialize sourcemaps
.pipe($.sourcemaps.init())
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Concatenate includes
.pipe($.include({
includePaths: [`${paths.to.js.in}`],
}))
// Transpile
.pipe($.babel())
// Catch errors
.pipe($.errorHandle())
// Save sourcemaps
.pipe($.sourcemaps.write('.'))
// Save unminified file
.pipe(gulp.dest(`${paths.to.js.out}`));
} else {
// Select bundle
bundle
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Concatenate includes
.pipe($.include({
includePaths: [`${paths.to.js.in}`],
}))
// Transpile
.pipe($.babel())
// Catch errors
.pipe($.errorHandle())
// Show file-size before compression
.pipe($.size({ title: 'Javascript In Size' }))
// Optimize and minify
.pipe($.terser())
// Show file-size after compression
.pipe($.size({ title: 'Javascript Out Size' }))
// Append suffix
.pipe($.rename({
suffix: '.min',
}))
// Save minified file
.pipe(gulp.dest(`${paths.to.js.out}`));
}
});

#babel/preset-env is not the same thing as #babel/preset-es2015 - the former turns plugins on and off based on your targeted browser compatibility metrics (which you can customize).
The docs say that if you don't explicitly specify the targets in the preset's config, the following defaults will be used:
Sidenote, if no targets are specified, #babel/preset-env behaves exactly the same as #babel/preset-es2015, #babel/preset-es2016 and #babel/preset-es2017 together (or the deprecated babel-preset-latest).
#babel/preset-es2015 alone, on the other hand, will only compile features that were added in the ES2015 version of the spec. This does not include newer features, such as async/await! If you want all of the features added since then, you will have to add all of the yearly presets. For this reason, it's recommended that you use the env preset.
If you switch https://babeljs.io to the #babel/preset-env preset (which is a seperate section below the list of yearly presets), you get the same output.

Related

Unexpected token keyword «function», expected punc «,»

Here is the error message after I try to run my app
[15:32:01] Starting 'default'...
[15:32:01] Plumber found unhandled error:
GulpUglifyError: unable to minify JavaScript
Caused by: SyntaxError: Unexpected token keyword «function», expected
punc «,»
File: /home/*******/myfile.js Line: 81
my gulp file:
const gulp = require('gulp')
const uglify = require('gulp-uglify')
const babel = require('gulp-babel')
const plumber = require('gulp-plumber')
const del = require('del')
gulp.task('default', ['conf'], () => gulp.src('src/app/**/*.js')
.pipe(plumber())
.pipe(babel())
.pipe(uglify())
.pipe(gulp.dest('dist')))
gulp.task('conf', ['package'], () => gulp.src('./src/conf/*').pipe(gulp.dest('dist/conf')))
gulp.task('package', ['clean'], () => gulp.src(['./package.json']).pipe(gulp.dest('dist/')))
gulp.task('clean', () => del(['dist/**/*']))
If I correctly understand the problem, my code has to be transpiled to es5 by babel, so here is the .babelrc
{
"plugins": [
"transform-class-properties",
"babel-plugin-transform-runtime",
"transform-es2015-shorthand-properties",
["babel-plugin-root-import", {
"rootPathSuffix": "src/app"
}]
],
"presets": ["es2015"]
}
Here is the code from line 81 (where the comments begin) from myfile.js.
export default class Scraper {
// ...
/**
* Converts a html string to a cheerio object
* #param {String} html The html string
* #return {Object} The cheerio object
*/
htmlToDom(html) {
// https://bugs.chromium.org/p/v8/issues/detail?id=2869
// https://github.com/cheeriojs/cheerio/issues/263
if(typeof global.gc === 'function') {
global.gc()
html = (' ' + html).substr(1)
}
return cheerio.load(html)
}
static absolute(location, relative) {
//...
}
First I thought maybe the shorthanded version causing the problem, but I have transform-es2015-shorthand-properties installed, and in an older project I use the very same skeleton, without this plugin.
Update
"dependencies": {
"babel-plugin-transform-class-properties": "^6.24.1",
"bunyan": "^1.8.10",
"cheerio": "^1.0.0-rc.2",
"colors": "^1.1.2",
"js-yaml": "^3.12.0",
"pg": "^7.4.3",
"puppeteer": "^1.5.0",
"sequelize": "^4.38.0",
"sequelize-connect": "^2.1.1"
},
"devDependencies": {
"ava": "^0.19.1",
"babel-plugin-root-import": "^6.1.0",
"babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-latest": "^6.24.1",
"babel-register": "^6.24.1",
"coveralls": "^2.13.0",
"del": "^2.2.2",
"esdoc": "^0.5.2",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-plumber": "^1.1.0",
"gulp-uglify": "^2.1.2",
"mkdir-recursive": "^0.4.0",
"nyc": "^11.2.0",
"sinon": "^2.1.0",
"standard": "^10.0.1",
"wait-on": "^3.2.0"
},
uninstalling and reinstalling gulp-uglify did the trick for me.
You may want to try adding babel-plugin-transform-async-to-generator
yarn add babel-plugin-transform-async-to-generator -D
.babelrc : "plugins": ["babel-plugin-transform-async-to-generator"]

nightwatch Error: Cannot find module 'e2e/step_definitions/analysis.js'

We have an angular 4 project and we're trying to add some e2e tests using gulp, nightwatch and cucumber but every time we run the tests the following error happens:
$ gulp e2e-tests
[11:15:12] Using gulpfile ~project/path/gulpfile.js
[11:15:12] Starting 'e2e-tests'...
[11:15:12] Starting 'e2e-scenarios'...
[11:15:12] log file
[11:15:12] Starting nightwatch...
Starting selenium server... started - PID: 18742
There was an error while starting the test runner:
Error: Cannot find module 'e2e/step_definitions/xxxx.js'
at Function.Module._resolveFilename (module.js:555:15)
at Function.Module._load (module.js:482:25)
at Module.require (module.js:604:17)
at require (internal/module.js:11:18)
at /project/path/node_modules/cucumber/lib/cli/index.js:163:16
at Array.forEach (<anonymous>)
Below is the configuration we have:
nightwatch.conf
var seleniumServer = require('selenium-server');
const chromedriver = require('chromedriver');
require('nightwatch-cucumber')({
cucumberArgs: ['--require', 'e2e/step_definitions', '--format', 'json:reports/cucumber.json', 'e2e/features']
});
module.exports = {
// Loads nightwatch-cucumber configuration into main nightwatch.js conf
custom_commands_path: '',
custom_assertions_path: '',
page_objects_path: '',
live_output: false,
disable_colors: false,
// Sets configuration for Selenium Server
selenium: {
start_process: true,
server_path: seleniumServer.path,
host: '127.0.0.1',
port: 4444,
cli_args : {
"webdriver.chrome.driver" : chromedriver.path
}
},
// Sets config options for different testing environments defined by the user
test_settings: {
default: {
launch_url: '',
selenium_port: 4444,
selenium_host: '127.0.0.1',
silent: true,
desiredCapabilities: {
browserName: 'chrome',
javascriptEnabled: true,
acceptSslCerts: true
},
'screenshots': {
enabled: true,
on_error: true,
on_failure: true,
path: '/screenshots'
}
},
chrome: {
desiredCapabilities: {
browserName: 'chrome',
javascriptEnabled: true,
acceptSslCerts: true
}
}
}
};
package.json
"devDependencies": {
"#angular/cli": "~1.6.0",
"#angular/compiler-cli": "^4.3.2",
"#angular/language-service": "^4.3.2",
"#types/jasmine": "~2.5.53",
"#types/jasminewd2": "~2.0.2",
"#types/node": "^6.0.104",
"codelyzer": "~3.0.1",
"gulp": "^3.9.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.4.2",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"selenium-webdriver": "^4.0.0-alpha.1",
"ts-node": "~3.0.4",
"tslint": "~5.3.2",
"typescript": "~2.3.3"
}
gulpfile.js
var gulp = require('gulp');
var nightwatch = require('gulp-nightwatch');
var reporter = require('gulp-protractor-cucumber-html-report');
var runSequence = require('run-sequence');
gulp.task('default', function() {
return console.log('Starting gulp tasks…');
});
gulp.task('login', function() {
return gulp.src('')
.pipe(nightwatch({
configFile: 'nightwatch.conf.js'
}))
});
//E2E tasks
gulp.task('e2e-scenarios', [], function e2e() {
let tags = '';
let skipTags = '';
let tagIndex = process.argv.indexOf("--tag");
let skipTagIndex = process.argv.indexOf("--skiptags");
if (tagIndex > -1) {
tags = process.argv[tagIndex + 1];
tags = '--tag ' + tags;
}
if (skipTagIndex > -1) {
skipTags = process.argv[skipTagIndex + 1];
skipTags = '--skiptags ' + skipTags;
}
return gulp.src('')
.pipe(nightwatch({
configFile: 'nightwatch.conf.js',
cliArgs: [tags, skipTags]
}));
});
gulp.task('e2e-report', function () {
return gulp.src('./reports/cucumber.json')
.pipe(reporter({
dest: 'reports/'
}));
});
gulp.task('e2e-tests', function (done) {
runSequence('e2e-scenarios', 'e2e-report', function () {
done();
});
});
And this is the project Structure
Project
enter image description here
Please help me to find out what is causing this issue.

webpack : is there a good hook / custom function to dump out resolved configuration?

I'm somewhat of a newbie with webpack and have been experimenting with easier ways to adjust/merge webpack configurations.
The following code, added to webpack/lib/webpack.js has been pretty helpful:
this is the standard webpack.js:
function webpack(options, callback) {
var compiler;
if(Array.isArray(options)) {
compiler = new MultiCompiler(options.map(function(options) {
return webpack(options);
}));
} else if(typeof options === "object") {
new WebpackOptionsDefaulter().process(options);
compiler = new Compiler();
compiler.options = options;
compiler.options = new WebpackOptionsApply().process(options, compiler);
new NodeEnvironmentPlugin().apply(compiler);
compiler.applyPlugins("environment");
compiler.applyPlugins("after-environment");
} else {
throw new Error("Invalid argument: options");
}
if(callback) {
if(typeof callback !== "function") throw new Error("Invalid argument: callback");
if(options.watch === true || (Array.isArray(options) &&
options.some(function(o) {
return o.watch;
}))) {
var watchOptions = (!Array.isArray(options) ? options : options[0]).watchOptions || {};
// TODO remove this in next major version
var watchDelay = (!Array.isArray(options) ? options : options[0]).watchDelay;
if(watchDelay) {
console.warn("options.watchDelay is deprecated: Use 'options.watchOptions.aggregateTimeout' instead");
watchOptions.aggregateTimeout = watchDelay;
}
return compiler.watch(watchOptions, callback);
}
compiler.run(callback);
}
this is my code:
//customization start
fs = require('fs');
var fnp_dump = 'webpack.dump.json';
fs.writeFile(fnp_dump, JSON.stringify(options, null, 2), function(err) {
if(err) {
return console.log(err);
}
console.log("dumping dump.webpack.js.final.json from webpack.js to: " + fnp_dump);
});
//customization end
return compiler;
}
The basic idea is that it dumps out the final json/js options object after webpack has finished sorting out the usual webpack.base.js + webpack.development.js. Since it's, at that point, just a fully-resolved javascript object, it doesn't really matter how the config.js files were written by individual developers.
Now you can diff options sent to webpack (this is an example of tranforming webpack 1 to webpack 2 configurations:
diff 003/webpack.dump.json 004/webpack.dump.json
< "loader": "style!css!postcss-loader!sass"
---
> "use": [
> {
> "loader": "style-loader"
> },
> {
> "loader": "postcss-loader"
> },
> {
> "loader": "sass-loader"
> }
> ]
However, I am customizing webpack.js directly and need to re-apply my patch after each npm update webpack. Is there a better way?
If your webpack.config.js is a function, you can call it on your own to resolve to an object.
If you have several configs (you mentioned webpack.base.js and webpack.development.js) you can use Webpack Merge to just combine your options to a single object, and then write it to the file system.
I would recommend you to have an own script in package.json to do this job, which you can then always call after your webpack job:
...,
"scripts": {
"dump-options": "scriptThatMergesConfigsAndWritesToFS.js",
"webpack-job": "webpack ... && npm run dump-options",
...
},
...
UPDATE
After some more research I realized, that the resolved options object is stored in the compiler object. The compiler object is passed to Plugins, and therefore you can easily write a Plugin that writes the config to a file, as I did here (not tested).
I also realized, that the Plugins cannot be stringified, as they are functions, so be aware of losing the Plugin configuration information.
I ended up writing my own plugin (and now notice that wtho wrote one too). It worked for me - note you need to have the bit of code that handles circular references:
// WebPackCompilationObserver.js
function WebPackCompilationObserver(options) {
WebPackCompilationObserver.options = options || {};
}
WebPackCompilationObserver.prototype.apply = function(compiler) {
compiler.plugin("emit", function(compilation, callback) {
var fs = require('fs');
var fnp_dump = WebPackCompilationObserver.options.dump_filename;
if (! fnp_dump) {
fnp_dump = "./dump.webpack.options.json";
console.log("please specify dump_filename path in the WebPackCompilationObserver.options, otherwise using default:" % fnp_dump);
}
if (fnp_dump){
console.log("dumping compilation.options to: " + fnp_dump);
var cache = [];
fs.writeFile(fnp_dump, JSON.stringify(compilation.options, function(key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
}, 2),
function(err) {
if (err) {
return console.log(err);
}
});
cache = null;
}
callback();
});
};
module.exports = WebPackCompilationObserver;
To use it:
webpack.config.development.js:
....
var WebPackCompilationObserver = require("./WebPackCompilationObserver");
....
config.plugins = config.plugins.concat([
....
,new WebPackCompilationObserver({dump_filename: '../dumpithere.json'})
])

native messaging host chrome-token-signing

I am trying to make an extension that will communicate with a native messaging host chrome-token-signing (https://github.com/open-eid/chrome-token-signing).
I have installed extension , but the EXE is not started. I have message log TEST: {"message":"Invalid argument","result":"invalid_argument"}
Do I need to do Something
I have installed the host in the registry like
HKEY_LOCAL_MACHINE\software\Google\Chrome\NativeMessagingHosts\ee.ria.esteid
and value C:\Users\dev\Desktop\chrome-token-signing\host-windows\ee.ria.esteid.json
The native application manifest.json:
{
"name": "ee.ria.esteid",
"description": "Give signatures with your eID on the web",
"path": "chrome-token-signing.exe",
"type": "stdio",
"allowed_origins": [
"chrome-extension://ckjefchnfjhjfedoccjbhjpbncimppeg/"
]
}
manifest.json of extension
{
"name": "Token signing",
"version": "0.0.24",
"minimum_chrome_version": "40.0",
"manifest_version": 2,
"description": "Use your eID smart card on the web",
"icons": {
"48": "icon48.png",
"128": "icon128.png"
},
"content_scripts": [{
"matches": ["*://*/*", "file:///*"],
"exclude_matches": ["*://www.overdrive.com/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": true
}],
"background": {
"scripts": ["background.js"]
},
"permissions": ["nativeMessaging"],
"applications": {
"gecko": {
"id": "{443830f0-1fff-4f9a-aa1e-444bafbc7319}"
}
}
}
background.js
var NO_NATIVE_URL = "https://open-eid.github.io/chrome-token-signing/missing.html";
var HELLO_URL = "https://open-eid.github.io/chrome-token-signing/hello.html";
var DEVELOPER_URL = "https://github.com/open-eid/chrome-token- signing/wiki/DeveloperTips";
var NATIVE_HOST = "ee.ria.esteid";
var K_SRC = "src";
var K_ORIGIN = "origin";
var K_NONCE = "nonce";
var K_RESULT = "result";
var K_TAB = "tab";
var K_EXTENSION = "extension";
// Stores the longrunning ports per tab
// Used to route all request from a tab to the same host instance
var ports = {};
// Probed to false if host component is OK.
var missing = true;
console.log("Background page activated");
// XXX: probe test, because connectNative() does not allow to check the presence
// of native component for some reason
typeof chrome.runtime.onStartup !== 'undefined' && chrome.runtime.onStartup.addListener(function() {
// Also probed for in onInstalled()
_testNativeComponent().then(function(result) {
if (result === "ok") {
missing = false;
}
});
});
// Force kill of native process
// Becasue Port.disconnect() does not work
function _killPort(tab) {
if (tab in ports) {
console.log("KILL " + tab);
// Force killing with an empty message
ports[tab].postMessage({});
}
}
// Check if native implementation is OK resolves with "ok", "missing" or "forbidden"
function _testNativeComponent() {
return new Promise(function(resolve, reject) {
chrome.runtime.sendNativeMessage(NATIVE_HOST, {}, function(response) {
if (!response) {
console.log("TEST: ERROR " + JSON.stringify(chrome.runtime.lastError));
// Try to be smart and do some string matching
var permissions = "Access to the specified native messaging host is forbidden.";
var missing = "Specified native messaging host not found.";
if (chrome.runtime.lastError.message === permissions) {
resolve("forbidden")
} else if (chrome.runtime.lastError.message === missing) {
resolve("missing");
} else {
resolve("missing");
}
} else {
console.log("TEST: " + JSON.stringify(response));
if (response["result"] === "invalid_argument") {
resolve("ok");
} else {
resolve("missing"); // TODO: something better here
}
}
});
});
}
// When extension is installed, check for native component or direct to helping page
typeof chrome.runtime.onInstalled !== 'undefined' && chrome.runtime.onInstalled.addListener(function(details) {
if (details.reason === "install" || details.reason === "update") {
_testNativeComponent().then(function(result) {
var url = null;
if (result === "ok" && details.reason === "install") {
// Also set the flag, onStartup() shall be called only
// on next startup
missing = false;
// TODO: Add back HELLO page on install
// once there is a nice tutorial
url = HELLO_URL;
} else if (result === "forbidden") {
url = DEVELOPER_URL;
} else if (result === "missing"){
url = NO_NATIVE_URL;
}
if (url) {
chrome.tabs.create({'url': url + "?" + details.reason});
}
});
}
});
// When message is received from page send it to native
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(sender.id !== chrome.runtime.id && sender.extensionId !== chrome.runtime.id) {
console.log('WARNING: Ignoring message not from our extension');
// Not our extension, do nothing
return;
}
if (sender.tab) {
// Check if page is DONE and close the native component without doing anything else
if (request["type"] === "DONE") {
console.log("DONE " + sender.tab.id);
if (sender.tab.id in ports) {
// FIXME: would want to use Port.disconnect() here
_killPort(sender.tab.id);
}
} else {
request[K_TAB] = sender.tab.id;
if (missing) {
_testNativeComponent().then(function(result) {
if (result === "ok") {
missing = false;
_forward(request);
} else {
return _fail_with (request, "no_implementation");
}
});
} else {
// TODO: Check if the URL is in allowed list or not
// Either way forward to native currently
_forward(request);
}
}
}
});
// Send the message back to the originating tab
function _reply(tab, msg) {
msg[K_SRC] = "background.js";
msg[K_EXTENSION] = chrome.runtime.getManifest().version;
chrome.tabs.sendMessage(tab, msg);
}
// Fail an incoming message if the underlying implementation is not
// present
function _fail_with(msg, result) {
var resp = {};
resp[K_NONCE] = msg[K_NONCE];
resp[K_RESULT] = result;
_reply(msg[K_TAB], resp);
}
// Forward a message to the native component
function _forward(message) {
var tabid = message[K_TAB];
console.log("SEND " + tabid + ": " + JSON.stringify(message));
// Open a port if necessary
if(!ports[tabid]) {
// For some reason there does not seem to be a way to detect missing components from longrunning ports
// So we probe before opening a new port.
console.log("OPEN " + tabid + ": " + NATIVE_HOST);
// create a new port
var port = chrome.runtime.connectNative(NATIVE_HOST);
// XXX: does not indicate anything for some reason.
if (!port) {
console.log("OPEN ERROR: " + JSON.stringify(chrome.runtime.lastError));
}
port.onMessage.addListener(function(response) {
if (response) {
console.log("RECV "+tabid+": " + JSON.stringify(response));
_reply(tabid, response);
} else {
console.log("ERROR "+tabid+": " + JSON.stringify(chrome.runtime.lastError));
_fail_with(message, "technical_error");
}
});
port.onDisconnect.addListener(function() {
console.log("QUIT " + tabid);
delete ports[tabid];
// TODO: reject all pending promises for tab, if any
});
ports[tabid] = port;
ports[tabid].postMessage(message);
} else {
// Port already open
ports[tabid].postMessage(message);
}
}
The native app is started and it replies to you that the arguments you give it are invalid.
You need to check with native app documentation and see what arguments are valid for that particular app and use them in the messages you send it from the extension. Your request will look like:
chrome.runtime.sendNativeMessage(NATIVE_HOST, {text: "some_valid_argument"}, function(response){
........

Inserting specific file at index of a stream

Basicly this gulp script finds the 'file1,file2,file3' in a folder, builds its dependencies (which are in the same folder) and add it all to 1 file.
Now, my problem is, i have a custom file which i have to put in after file2. How can i achieve this?
function gatherAMD(stream, file) {
var moduleId = file.path.match(/file\.(.+)\.js/)[1];
return stream.pipe(amdOptimize(`file.${moduleId}`, {
baseUrl: "fileslocation/location",
exclude: [ 'jquery' ]
}));
}
gulp.task("js", function() {
var included = [];
var files = "file1,file2,file3"
var stream = null;
if (files.indexOf(",") == -1) {
stream = gulp.src('fileslocation/location/file.'+ files+ '.js', { base: "fileslocation/location"});
} else {
stream = gulp.src(`fileslocation/location/file.{${files}}.js`, { base: "fileslocation/location"});
}
return stream.pipe(debug())
.pipe(foreach(gatherAMD))
.pipe(filter(function(file) {
if (included.indexOf(file.path) === -1) {
included.push(file.path);
return true;
} else {
return false;
}
}))
.pipe(concat({path: 'fileslocation/custom.js', base: 'fileslocation'}))
.pipe(gulp.dest("fileslocation"));
});
You can probably use map for checking the current file in the stream, and then adding it from some logic and then using gulp-inject to add a file to the stream.
Something like,
return stream.pipe(debug())
.pipe(foreach(gatherAMD))
.pipe(filter(function(file) {
if (included.indexOf(file.path) === -1) {
included.push(file.path);
return true;
} else {
return false;
}
}))
.pipe(map(function(file, callback) {
if (file.relative === 'file2.js') {
// inject file to the stream here
}
callback(null, file);
}))
.pipe(concat({path: 'fileslocation/custom.js', base: 'fileslocation'}))
.pipe(gulp.dest("fileslocation"));