pfaffman
(Jay Pfaffman)
August 25, 2023, 2:54pm
1
from How to require external libraries in a component helper file? - #2 by merefield
Hey @merefield – Is this still how to do this?
I’m trying to pul in qrcode.js to generate a QRcode in the browser.
I’m getting blocked by CSP as well. I don’t understand how it’s a CSP problem if it’s on the same host. This is on a production server using discourse_theme
to debug.
I’m putting this in an initializer:
import loadScript from "discourse/lib/load-script";
import { withPluginApi } from "discourse/lib/plugin-api";
// import QRCode from "discourse/lib/qrcode";
export default {
name: "qrcode",
ensureQRCode() {
window.console.log(settings.theme_uploads.QRCode);
return loadScript(settings.theme_uploads.QRCode).then(() => {
return loadScript(settings.theme_uploads.QRCode);
});
},
initialize(container) {
withPluginApi("0.8.7", (api) => {
api.decorateCookedElement((cooked, postWidget) => {
const placeholderNodes = cooked.querySelectorAll(
".d-wrap[data-wrap=qrcode]"
);
this.ensureQRCode();
// const qr = new QRCode(
// document.getElementById("qrcode"),
// "http://jindo.dev.naver.com/collie"
// );
...
And it seems that the function doesn’t get called to load the script if I don’t call this.ensureQRCode();
, which you don’t seem to be doing in your component.
The script is available and I can retrive it (so I got the stuff in the about.json
and /assets/qrcode.js
right), but the browser refuses to load it.
2 Likes
The result of your loadscript is a promise so you need to put your code relying on it in a .then
block as per my example code
3 Likes
Lilly
August 25, 2023, 3:04pm
3
I don’t know if this is a similar thing (I suspect it isn’t) but holy smoly is it driving me nuts because this should be simple to do.
import { default as userCardContents } from "discourse/components/user-card-contents";
import DiscourseURL from "discourse/lib/url";
export default userCardContents.extend({
_show(_, target) {
DiscourseURL.routeTo(`${target.href}/summary`);
return false;
},
});
1 Like
pfaffman
(Jay Pfaffman)
August 25, 2023, 3:05pm
4
Thanks very much!
But I thought I did that:
return loadScript(settings.theme_uploads.QRCode).then(() => {
return loadScript(settings.theme_uploads.QRCode);
});
I tried very hard to change your example as little as possible
Maybe I need to use a .then
when I’m trying to use the code later?
But that doesn’t solve the CSP issue, does it?
2 Likes
Falco
(Falco)
August 25, 2023, 3:17pm
5
My two main advices are:
Put the library in the assets folder
This solves CSP, makes the theme self-contained and is considered a good practice, instead of loading it from third-parties.
Load it lazily
Only when needed, you can load it lazily using await loadScript
. This means it won’t be loaded in pages where it isn’t needed, slowing your whole site.
A good example of a theme that follows those good practices is GitHub - discourse/discourse-mermaid-theme-component
6 Likes
Yes, precisely. . That’s how it works in my example.
3 Likes
pfaffman
(Jay Pfaffman)
August 25, 2023, 9:20pm
7
One more question: What’s the difference between ...initializers/mycode.js
and ...api-initializers/mycode.js
?
And much thanks to both of you!!
That was a good example! I was able to make sense of it!
Well, I thought I followed your example. Javascript still seems like a twisty maze of passages that all look alike.
3 Likes