Disable cachebusting string Ember-CLI production build - ember-cli

I need to have images in my Ember-CLI application for which I change the path dynamically, i.e. <img src="my_dynamic_path">.
However, because Ember adds a cachebusting string to all the images, I can't do this.
Is there any way to disable the cachebusting string, or some function that finds a URL of a cachebusted image-name, or a folder which is unaffected by this behavior?

There are a few things that you can do, ember-cli uses broccoli-asset-rev to fingerprint files.
You can either disable fingerprinting:
var app = new EmberApp({
fingerprint: {
enabled: false
}
});
You can choose to exclude certain directories/files:
var app = new EmberApp({
fingerprint: {
exclude: ['my/ignored/directory']
}
});
For more information regarding fingerprinting check out asset compilation in the docs.

Related

GitHub: How to get `utteranc.es` to work for website discussion

My website https://friendly.github.io/HistDataVis/ wants to use the seemingly light weight and useful discussion feature offered by the https://github.com/utterance app.
I believe I have installed it correctly in my repo, https://github.com/friendly/HistDataVis, but it does not appear on the site when built.
I'm stumped on how to determine what the problem is, or how to correct it. Can anyone help?
For reference, here is my setup:
The website is built in R Studio, using distill in rmarkdown.
I created utterances.html with the standard JS code recommended.
<script>
document.addEventListener("DOMContentLoaded", function () {
if (!/posts/.test(location.pathname)) {
return;
}
var script = document.createElement("script");
script.src = "https://utteranc.es/client.js";
script.setAttribute("repo", "friendly/HistDataVis");
script.setAttribute("issue-term", "og:title");
script.setAttribute("crossorigin", "anonymous");
script.setAttribute("label", "comments ??");
/* wait for article to load, append script to article element */
var observer = new MutationObserver(function (mutations, observer) {
var article = document.querySelector("d-article");
if (article) {
observer.disconnect();
/* HACK: article scroll */
article.setAttribute("style", "overflow-y: hidden");
article.appendChild(script);
}
});
observer.observe(document.body, { childList: true });
});
</script>
In one Rmd file, I use in_header to insert this into the generated HTML file:
---
title: "Discussion"
date: "`r Sys.Date()`"
output:
distill::distill_article:
toc: true
includes:
in_header: utterances.html
---
Also used this in my _site.yml file to apply to all Rmd files on the site.
On my GitHub account, I installed utterances under GitHub apps, and gave it repository access to the repo for this site.
Edit2
Following the solution suggested by #laymonage, I fixed the script. I now get the Comments section on my web page, but get an error, "utterances not installed" when I try to use it. Yet, utterances is installed, as I just checked.
This part of your code:
if (!/posts/.test(location.pathname)) {
return;
}
Prevents the rest of the script to load because it's always true.
The condition checks whether the value of location.pathname passes the regular expression test string posts and negates it (!). That means the condition is true if the location.pathname (the path name of the current URL, e.g. /HistDataVis/ for https://friendly.github.io/HistDataVis/) does not contain posts anywhere in the string. None of the pages on your website has posts in the pathname, so the script will end there.
It should work if you change /posts/ to /HistDataVis or just remove the if block altogether.
Alternatively, you can also try giscus, a similar project that uses GitHub Discussions instead of Issues. Someone already made a guide on how to use it with Distill. Disclaimer: I'm the developer of giscus.

How to configure GatsbyJS firestore plugin re. timestampsInSnapshots change

I have installed and configured the gatsby-source-firestore plugin.
When I run 'gatsby develop', the app launches.
In the terminal however, the following warning appears:
The behavior for Date objects stored in Firestore is going to change
AND YOUR APP MAY BREAK.
To hide this warning and ensure your app does not break, you need to
add the following code to your app before calling any other Cloud
Firestore methods:
const firestore = new Firestore();
const settings = {/* your settings... */ timestampsInSnapshots:
true};
firestore.settings(settings);
With this change, timestamps stored in Cloud Firestore will be read
back as Firebase Timestamp objects instead of as system Date objects.
So you will also need to update code expecting a Date to instead
expect a Timestamp...
The question is: how do I implement this change requirement into my firestore gatsby plugin?
This is handled at a plugin level.
This behavior is also mentioned on Github here: https://github.com/taessina/gatsby-source-firestore/issues/12
The Github repo has been updated to avoid the alert but the maintainer hasn't updated the plugin on npm.
I suggested a temporary solution until he does.
You can install the plugin from the master branch on Github with
yarn add taessina/gatsby-source-firestore#master
or
npm i taessina/gatsby-source-firestore#master
Make sure to handle timestamps properly. My gatsby config looks something like that:
{
resolve: 'gatsby-source-firestore',
options: {
credential: firestoreCredential,
types: [
{
type: 'FirestoreEvent',
collection: 'events',
map: ({
timeStart,
}) => ({
timeStart: timeStart.toDate(),
}),
},
],
},
},

sails.js setup: How to make a node module available across the sails project (controller / model, etc)?

I just getting started with SailsJS as my first web framework on Node. Let's say I wanna add MomentJS in and use across the app. How to set it up?
you can use the bootstrap.js (in config/)
like:
module.exports.bootstrap = function (cb) {
sails.moment = require('moment');
cb();
};
in all Sails-Files you can use
sails.moment()
now.
If you're trying to include your node_modules into the client side, such as jQuery, AngularJS or one of the various many font libraries, then you can npm install them as normal, but just to be sure in sails you edit your tasks/config/copy.js and add a new block, example:
grunt.config.set('copy', {
dev: {
files: [{
expand:true,
cwd: './node_modules/font-awesome/fonts',
src: ['**/*'],
dest: '.tmp/public/fonts'
}
}
});
LESS can be #imported like normal without being copied around. Other assets will need to be copied as above. If you're using the sails linker then don't forget to add your JS paths to tasks/pipeline.js too (if necessary).
You can read more here:
http://ash.zi.vc/sails/2016/02/02/including-client-side-node-modules-in-my-sails-application/
It's not directly obvious how to sync npm modules to the web accessible directories.
SailsJS is no different to any other NodeJS app. So on top of your (say) Controller.js file, you do
var m = require("moment");
And you're good to go. #mdunisch's method will obviously let you use the moment package throughout your app, without having to do "require" in each file.

Image not showing immediately after uploading in sails.js

In my application ,I have stored uploaded images to folder ./assets/uploads. I am using easyimage and imagemagick for storing the images.
In my application, after uploading the images, it should show the new uploaded image. But it is not displayed even if the page is refreshed. But when i do sails lift , the image is shown.
How to show image immediately after uploading the image? Thanks a lot!
It's a totally normal situation, because of the way Sails works with the assets.
The thing is that upon sails lift the assets are being copied (including directory structure and symlinks) from ./assets folder to ./.tmp/public, which becomes publicly accessible.
So, in order to show your images immediately after upload, you, basically, need to upload them not to ./assets/uploads but to ./.tmp/public/uploads.
The only problem now is that the ./.tmp folder is being rewritten each time your application restarts, and storing uploads in ./tmp/... would make them erased after every sails lift. The solution here would be storing uploads in, for example, ./uploads and having a symlink ./assets/uploads pointing to ../uploads.
Though this question is pretty old but I would like to add a solution which I just implemented.
Today I spend almost 4 hours trying all those solutions out there. But none helped. I hope this solution will save someone else's time.
WHY images are not available immediately after uploading to any custom directory?
Because according to the default Sails setup, you can not access assets directly from the assets directory. Instead you have to access the existing assets that is brought to .tmp/public directory by Grunt at time of sails lift ing
THE Problems
(Available but Volatile) If you upload a file (say image) anywhere inside .tmp/public
directory, your file (image) is going to erase at next sails lift
(Unavailability) If you upload a file in any other custom directory- say: ./assets/images, the uploaded file will not be available immediately but at next sails lift it will be available. Which doesn't makes sense because - cant restart server each time files gets uploaded in production.
MY SOLUTION (say I want to upload my images in ./assets/images dir)
Upload the file say image.ext in ./tmp/public/images/image.ext (available and volatile)
On upload completion make a copy of the file image.ext to ./assets/images/*file.ext (future-proof)
CODE
var uploadToDir = '../public/images';
req.file("incoming_file").upload({
saveAs:function(file, cb) {
cb(null,uploadToDir+'/'+file.filename);
}
},function whenDone(err,files){
if (err) return res.serverError(err);
if( files.length > 0 ){
var ImagesDirArr = __dirname.split('/'); // path to this controller
ImagesDirArr.pop();
ImagesDirArr.pop();
var path = ImagesDirArr.join('/'); // path to root of the project
var _src = files[0].fd // path of the uploaded file
// the destination path
var _dest = path+'/assets/images/'+files[0].filename
// not preferred but fastest way of copying file
fs.createReadStream(_src).pipe(fs.createWriteStream(_dest));
return res.json({msg:"File saved", data: files});
}
});
I dont like this solution at all but yet it saved more of my time and it works perfectly in both dev and prod ENV.
Thanks
Sails uses grunt to handle asset syncing. By default, the grunt-watch task ignores empty folders, but as long as there's at least one file in a folder, it will always sync it. So the quickest solution here, if you're intent on using the default static middleware to server your uploaded files, is to just make sure there's always at least one file in your assets/uploads folder when you do sails lift. As long as that's the case, the uploads folder will always be synced to your .tmp/public folder, and anything that's uploaded to it subsequently will be automatically copied over and available immediately.
Of course, this will cause all of your uploaded files to be copied into .tmp/public every time your lift Sails, which you probably don't want. To solve this, you can use the symlink trick #bredikhin posted in his answer.
Try to do this:
npm install grunt-sync --save-dev --save-exact
uncomment the line: // grunt.loadNpmTasks('grunt-sync');
usually it is near to the end of the file /tasks/config/sync.js.
lift the App again
Back to the Original answer
I was using node version 10.15.0, and I faced same problem. I solved this by updating to current version of node(12.4.0) and also updated npm and all the node modules. After this, I fixed the vulnerabilities(just run 'npm audit fix') and the grunt error that was coming while uploading the images to assets/images folder was fixed.
Try out this implementation
create a helper to sync the file
example of the filesync helper
// import in file
const fs = require('fs')
module.exports = {
friendlyName: 'Upload sync',
description: '',
inputs: {
filename:{
type:'string'
}
},
exits: {
success: {
description: 'All done.',
},
},
fn: async function ({
filename
}) {
var uploadLocation = sails.config.custom.profilePicDirectory + filename;
var tempLocation = sails.config.custom.tempProfilePicDirectory + filename;
//Copy the file to the temp folder so that it becomes available immediately
await fs.createReadStream(uploadLocation).pipe(fs.createWriteStream(tempLocation));
// TODO
return;
}
};
now call this helper to sync your files to the .temp folder
const fileName = result[0].fd.split("\\").reverse()[0];
//Sync to the .temp folder
await await sails.helpers.uploadSync(fileName);
reference to save in env
profilePicDirectory:path.join(path.resolve(),"assets/images/uploads/profilePictures/")
tempProfilePicDirectory:path.join(path.resolve(),".tmp/public/images/uploads/profilePictures/"),
also can try
process.cwd()+filepath

Karma - Unexpected token when including an html file

I'm trying to include an simple html file in my karma config file to access the html elements from my javascript files and test this with jasmine in karma.
But I'm getting always an Unexpected token < error. I saw in an webcast that it is possible to include html files, but I don't know why it doesn't works with my configuration?
Thanks in advance
By karma config you have to register every file your want to use in your tests. You can do that by adding patterns to your files array in your config.
A file pattern looks like this:
files: [
{
pattern: 'test/unit/*.js',
watched: true, //watching file modifications for test autorun
included: true, //included as <script src="..."> in the runner html file
served: true //used by tests (the test server should serve it)
}
]
You can use short pattern syntax:
files: [
'test/unit/*.js'
]
This means exactly the same as the previous pattern.
If you don't want to use your file in your test included as <script src="file.js"></script>, then you have use included: false and load the file from within your tests via AJAX. Be aware that you should use relative urls for that, because the domain of the test server can always change...
The pattern order is important too, it uses reverse overriding:
files: [
{pattern: '*.js', included: true}
{pattern: '*.js', included: false}
]
In this case every js file will be included, so the first pattern overrides the second.
For example by html files:
karma config:
files: [
{pattern: 'bootstrap.js', included: true}
{pattern: 'x.html', included: false}
]
bootstrap.js:
var xhr = new XMLHttpRequest();
xhr.open('get', '/base/x.html', false);
xhr.send();
console.log(xhr.status, xhr.responseText); //200, '<html content>'
The URI always has a /base prefix because Karma stores its own index.html and js files on the top level, so it needs a subfolder. If you want to find out what URIs are served, you can use this code:
var servedUris = Object.keys(window.__karma__.files);
I wrote some basic fs stuff to support sync read by Yadda: https://github.com/acuminous/yadda/blob/master/lib/shims/karma-fs.js You might be able to move it to a different project extend it, and use fs instead of AJAX in browser. At least that's how I would do it with Browserify.
I ended up making a simple patch to the lib/middleware/karma.js file in my Karma installation. It uses an extension .literal to denote "just echo the entire file onto the page". I've always found it strange that Karma doesn't have an inbuilt way to do this. My way is certainly not brilliantly-constructed but it might be good enough for you.
With this you can just have in your karma.conf.js:
// ...
files: [
"path/to/my_html.literal", // Echoed directly onto the page
"path/to/other.js", // Normal behaviour
// ...
],
My nested scriptTags function (inside createKarmaMiddleware) just looks like this:
var scriptTags = files.included.map(function(file) {
var filePath = file.path;
var fileExt = path.extname(filePath);
// Include .literal files directly into the body of the HTML.
if (filePath.match(/.literal$/)) {
var fs = require("fs");
return fs.readFileSync(filePath, "utf-8");
}
// ...
The diff is here: https://github.com/amagee/karma/commit/c09346a71fc27c94cc212a2bd88b23def19ec3a4
You need use the html2js preprocessor (or the ng-html2js preprocessor if using AngularJS). See the preprocessor description for how it works.
Since Karma 0.10, the html2js preprocessor is shipped with Karma and configured by default:
module.exports = function(config) {
config.set({
files: [
'templates/*.html'
],
preprocessors: {
'**/*.html': ['html2js']
}
});
};
Then you can access the html content as JS string:
var elm = $(__html__['templates/x.html'])
The error you are getting means that the HTML files are not preprocessed. By default, all HTML files under the basePath are preprocessed, so maybe your HTML files are somewhere else, in which case you need to put them in the preprocessors config explicitly. Share your karma.conf.js if you need more help.