The short question I have: based on the below code, why do I have to 'import' the components below twice to get my code to work?
I am working in a pretty locked-down environment, so cannot use Webpack or .vue SFCs at the moment, or npm (for all intents and purposes).
I've cobbled together a working version of a small vue app using typescript files, but am confused why it worked :S.
I have to import the component file, then require it as a component. I'd like to clean this up if I could, as we will be rolling this out as a P.O.C. with developers that are also just learning Vue, so I'd like to avoid bad practices at the start if I could.
index.ts
import * as Vue from "vue";
import * as Apple from "./App"; <-----
Vue.component('apple2', Apple.default); <----- wat?
let v = new Vue({
el: "#app",
components: { Apple}, <-----
template: `
<div>
<apple2/> <-----
</div>`,
data: {
name: "World"
},
});
App.ts
import * as Vue from "vue";
import * as fred from "./Hello"; <----
Vue.component('fred2', fred.default); <----
export default Vue.extend({
name: 'Apple',
template: `
<div>
<fred2 :name="name" :initialEnthusiasm="4"/> <-----
</div>`,
data() {
return { name: "World" }
},
components: { fred } <-----
});
Index.html
<!doctype html>
<html>
<head>
<script src="scripts/vue.min.js"></script>
<script data-main="scripts/build/index" src="scripts/lib/require.min.js">
</script></head>
<body>
<div id="app"></div>
</body>
tsConfig
{"compileOnSave": true,
"compilerOptions": {
"module": "amd",
"moduleResolution": "node",
"noImplicitAny": true,
"noEmitOnError": false,
"outDir": "./scripts/build",
"removeComments": false,
"sourceMap": true,
"target": "es5",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"exclude": [
"node_modules",
"wwwroot"
],
"include": [
"./scripts/**/*"
]
}
You're mixin up two different concepts, when you do this:
Vue.component('apple2', Apple.default);
You're actually registering the component definition object (Apple.default) with the name apple2 with the global Vue instance, making it available to all the components that are rendered by the previously referred Vue instance. In this case you could remove this part of your code in the index.ts:
components: { Apple}
And in theory your app should still work.
But because you're using typescript you can make your app work as if it was using a module system, allowing you to import the used sub-components in each parent component, allowing you to do something like this:
App.ts
export default const component = {
template: '<div>My component</div>'
}
index.ts
import Vue from 'vue';
import component from './App';
new Vue({
el: '#app',
components: {
'my-imported-component': component
}
});
And in your template:
<div id="app">
<my-imported-component/>
</div>
This would be, in my opinion a better approach because that you won't pollute the global Vue instance with all your components, but it's a matter of taste and what works for your scenario.
For more information take look at this link:
https://v2.vuejs.org/v2/guide/components-registration.html
Related
I saw in the swagger ui documentation that you can provide a urls parameter which is:
An array of API definition objects ({url: "", name: ""}) used by Topbar plugin. When used and Topbar plugin is enabled, the url parameter will not be parsed. Names and URLs must be unique among all items in this array, since they're used as identifiers.
I was hoping that this will give me a selector from which I can chose which of my yaml files to process. Unfortunately, it doesn't seem to do anything.
Here is my code:
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
urls: [
{url:"http://test.dev/documentation/microservices/microservices.yaml",name:"All Microservices"},
{url:"http://test.dev/documentation/microservices/plans.yaml",name:"Plans"},
],
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
window.ui = ui
}
I'd also like to set the primaryName to All Microservices.
Any ideas on where I'm going wrong?
The urls configuration option is supported in Swagger UI 3.0.18 and later.
You can use it instead of url like this:
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
urls: [
{url: "https://path/to/api1.yaml", name: "API One"},
{url: "https://path/to/api2.yaml", name: "API Two"},
],
"urls.primaryName": "API Two" // default document (if other than the first)
...
})
Result:
We have an electron crypto app that signs transactions (among other things).
We want other websites to have the ability to have a button that opens that electron app, pre-filled with some params (the transaction information).
flow is:
user clicks "make transaction" on some-crypto-site.com
electron app opens up with pre-filled params
user clicks "sign transaction" in electron app
electron app does stuff behind the scenes
electron app closes and sends a message to some-crypto-site.com
This could be done at runtime, or install time.
What I tried (linux, chrome)
calling app.setAsDefaultProtocolClient with the code of this gist, which is basically:
app.setAsDefaultProtocolClient("my-app")
But after I put my-app://foo?bar=baz in chrome browser, I get the following popup, and pressing open-xdg does nothing (other than dismissing the popup)
I looked into
Electron protocol api which seems to handle in-app protocols only
webtorrent .desktop file This might be the way to go, I'm just not sure how to go about it.
Maybe there's a way to do so at install time through electron builder?
Thanks in advance for the help, I have no idea how to proceed here!
Resources that might be useful
github repo with mac+window example
github comment for linux
github comment for linux 2
SO answer for all 3 OSs
SO windows answer
npm package for windows registery
SO mac answer
SO linux answer
microsoft docs for windows
windows article
github comment for windows
github comment for mac
info.plst for mac
old repo for mac and win
Since this may be relevant to what I’m doing at work, I decided to give it a go.
I’ve only tested this on OSX though!
I looked at the documentation for app.setAsDefaultProtocolClient and it says this:
Note: On macOS, you can only register protocols that have been added to your app's info.plist, which can not be modified at runtime. You can however change the file with a simple text editor or script during build time. Please refer to Apple's documentation for details.
These protocols can be defined when packaging your app with electron-builder. See build:
{
"name": "foobar",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron .",
"dist": "electron-builder"
},
"devDependencies": {
"electron": "^3.0.7",
"electron-builder": "^20.38.2"
},
"dependencies": {},
"build": {
"appId": "foobar.id",
"mac": {
"category": "foo.bar.category"
},
"protocols": {
"name": "foobar-protocol",
"schemes": [
"foobar"
]
}
}
}
In your main thread:
const {app, BrowserWindow} = require('electron');
let mainWindow;
function createWindow () {
mainWindow = new BrowserWindow({width: 800, height: 600})
mainWindow.loadFile('index.html');
}
app.on('ready', createWindow);
var link;
// This will catch clicks on links such as open in foobar
app.on('open-url', function (event, data) {
event.preventDefault();
link = data;
});
app.setAsDefaultProtocolClient('foobar');
// Export so you can access it from the renderer thread
module.exports.getLink = () => link;
In your renderer thread:
Notice the use of the remote API to access the getLink function exported in the main thread
<!DOCTYPE html>
<html>
<body>
<p>Received this data <input id="data"/></p>
<script>
const {getLink} = require('electron').remote.require('./main.js');
document.querySelector('#data').value = getLink();
</script>
</body>
</html>
Example
open in foobar
This also allows you to launch from the command line:
open "foobar://xyz=1"
How do you get back to the original caller?
I suppose that when you launch the app you could include the caller url:
<a href="foobar://abc=1&caller=example.com”>open in foobar</a>
When your electron app finishes processing data, it would simply ping back that url
Credits
Most of my findings are based on:
From this GitHub issue
And the excellent work from #oikonomopo
All little bit different from above.
open-url fires before the ready event so you can store it in a variable and use within the widow did-finish-load.
let link;
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1280,
height: 720,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
mainWindow.openDevTools();
mainWindow.setContentProtection(true);
mainWindow.loadFile('index.html');
mainWindow.webContents.on("did-finish-load", function() {
mainWindow.webContents.send('link', link);
});
}
app.on('ready', createWindow);
// This will catch clicks on links such as open in foobar
app.on('open-url', function(event, url) {
link = url;
if (mainWindow?.webContents) {
mainWindow.webContents.send('link', link);
}
});
app.setAsDefaultProtocolClient('protocols');
You can then use the value in your render html like this.
<!DOCTYPE html>
<html>
<head></head>
<body>
<script>
const ipc = require("electron").ipcRenderer;
ipc.on("link", function (event, url) {
console.log(url);
console.log(parseQuery(decodeURI(url)));
});
function parseQuery(queryString) {
queryString = queryString.substring(queryString.indexOf("://") + 3);
var query = {};
var pairs = (queryString[0] === "?" ? queryString.substr(1) : queryString).split("&");
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split("=");
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || "");
}
return query;
}
</script>
</body>
</html>
In our swagger.json we are setting basePath to /api, however, when the application is deployed in docker container, the context path is not /api. This could be different thing and we don't know what it is so we can't hard code it.
I am trying to set requestInterceptor as per the following guide, in order to catch the request and modify the url path perhaps:
https://swagger.io/docs/swagger-tools/#customization-36
But it seems requestInterceptor is being ignored. Is this possible? If not, how can I set the correct path at runtime?
This is my code in index.html
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
url: "../api-docs/swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
requestInterceptor: function(request) {
window.alert(request);
},
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
window.ui = ui
}
We are using Swagger 2.0
Upgrade to the latest version from here, or update your node package. I had the same problem because I downloaded the distribution before requestInterceptor support was added.
I'm trying to use vue.js inside electron app but getting the following error:
Uncaught Exception: ReferenceError: document is not defined
at query (/Users/LM/Documents/mongoui/node_modules/vue/dist/vue.common.js:1070:10)
at Vue._initProps (/Users/LM/Documents/mongoui/node_modules/vue/dist/vue.common.js:7254:23)
at Vue._initState (/Users/LM/Documents/mongoui/node_modules/vue/dist/vue.common.js:7235:10)
at Vue._init (/Users/LM/Documents/mongoui/node_modules/vue/dist/vue.common.js:2394:10)
at new Vue (/Users/LM/Documents/mongoui/node_modules/vue/dist/vue.common.js:9000:8)
at Object. (/Users/LM/Documents/mongoui/main.js:11:1)
at Module._compile (module.js:425:26)
at Object.Module._extensions..js (module.js:432:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:313:12)
This is how I load vue.js inside main.js:
var Vue = require('vue');
new Vue({
el: "#app",
data: {
collections: [
{"name": "test 1"},
{"name": "test 2"},
{"name": "test 3"}
]
}
});
Given your error:
Uncaught Exception: ReferenceError: document is not defined at query
I would assume you're trying to use Vue inside of the Main Process, which unfortunately Vue wont be able to do without something like jsdom, since Vue depends on the document, and the main process doesn't have a document.
But, I assume the issue starts more fundamentally. You're probably wanting to use Vue from a Render Process, since that's where the document can be accessed.
Essentially, the main process in Electron is like the all-mighty controller, it is where you spawn and manage render processes. It doesn't reference to any singular DOM because no DOM exists in the main process. Instead, consider render processes, render processes are things like BrowserWindow, which can have a DOM.
So, with that information, we could try something like this:
main.js:
// import { app, BrowserWindow } from 'electron';
var electron = require('electron'),
app = electron.app,
BrowserWindow = electron.BrowserWindow;
app.on('ready', function() {
var main = new BrowserWindow({ /* ... */ });
main.loadURL('file://' + __dirname + '/index.html');
});
Then, from your render process:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example</title>
<script>
var Vue = require('vue');
new Vue({
el: "#app",
data: {
collections: [
{"name": "test 1"},
{"name": "test 2"},
{"name": "test 3"}
]
}
});
</script>
</head>
<body id='app'>
</body>
</html>
Of course you can reorganize the files however you want to, just remember to use Vue inside of the render process instead of the main process.
Edit 11/4/2016
Vue has server side rendering now too which you might want to look at.
I have Chrome extension that loads jquery-1.8.3.min.js and jquery-ui.js and jquery-ui-base64.css into the content script .
i use them in the content script NOT background script .
i set the configuration ( i think ) right but when i see in the console i getting errors
i can see the icons in the windows just fine , but i still getting the errors in the Chrome window.
is it a bug in chrome im using version 23.0.1271.95 m?
this is the manifist :
{
"name":"Sample communication from content to background",
"description":"This is a sample for Simulating communication from content to background",
"manifest_version":2,
"version":"2",
"background":{
"scripts":["background.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery-1.8.3.min.js","jquery-ui.js","client.js"],
"run_at":"document_end",
"all_frames": true,
"css":["jquery-ui-base64.css"]
}
],
"web_accessible_resources": [
"client.js","jquery-1.8.3.min.js","jquery-ui.js","jquery-ui-base64.css",
"images/ui-bg_flat_0_aaaaaa_40x100.png",
"images/ui-bg_flat_75_ffffff_40x100.png",
"images/ui-bg_glass_55_fbf9ee_1x400.png",
"images/ui-bg_glass_65_ffffff_1x400.png",
"images/ui-bg_glass_75_dadada_1x400.png",
"images/ui-bg_glass_75_e6e6e6_1x400.png",
"images/ui-bg_glass_95_fef1ec_1x400.png",
"images/ui-bg_highlight-soft_75_cccccc_1x100.png",
"images/ui-icons_222222_256x240.png",
"images/ui-icons_2e83ff_256x240.png",
"images/ui-icons_454545_256x240.png",
"images/ui-icons_888888_256x240.png",
"images/ui-icons_cd0a0a_256x240.png"
],
"permissions": [
"unlimitedStorage",
"http://*/",
"<all_urls>",
"tabs"
]
}
in the jquery-ui-base64.css i changed all the imags url load to something like this :
url(chrome-extension://__MSG_##extension_id__/chrome-extension://__MSG_##extension_id__/images/ui-bg_flat_75_ffffff_40x100.png)
url(chrome-extension://__MSG_##extension_id__/chrome-extension://__MSG_##extension_id__/images/ui-bg_highlight-soft_75_cccccc_1x100.png)
but still im getting the errors:
Denying load of chrome-extension://mmoccjinakdjcmhjdjghhjnihbfkkgkp/chrome-extension://mmoccjinakdjcmhjdjghhjnihbfkkgkp/images/ui-bg_flat_75_ffffff_40x100.png. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.
Denying load of chrome-extension://mmoccjinakdjcmhjdjghhjnihbfkkgkp/chrome-extension://mmoccjinakdjcmhjdjghhjnihbfkkgkp/images/ui-bg_highlight-soft_75_cccccc_1x100.png. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.
the images are there in the images dir and i can see the icons in the JQuery dialog i created.
EDIT 1)
The following code works for all background\extension related DOM and css
manifest.json
Simple json structure with all permissions defined
{
"name": "My extension",
"version": "1.0",
"permissions": [
"http://*/*", "tabs", "https://*/*"
],
"browser_action": {
"default_icon": "icon.jpg",
"default_popup":"popup.html"
},
"manifest_version": 2
}
popup.html
Linked style sheet for Browser action Popup
<html>
<head>
<link rel="stylesheet" href="styles.css"></link>
</head>
<body>
</body>
</html>
styles.css
used url() for image path
body{
width : 500px;
height: 500px;
background-image: url('img/icon.jpg');
}
Let me know if it still fails
EDIT 2)
For Injecting Images through content stuff
Solution a)
Using this converter, you convert your image to base64 strings and you can use them as
{ background-image: url(data:image/png;base64,iVBORw ........ };
Solution b)
The following code will not work because
{
background-image:url(chrome.extension.getURL('img/icon.jpg'));
}
chrome.extension.getURL() is undefined for css.
So, i used js for injection of background-images\any image URL's(Because they have dynamic URL's)
manifest.json
Simple json structure with all permissions defined for content scripts and css
{
"name": "My extension",
"version": "1.0",
"permissions": [
"http://*/*", "tabs", "https://*/*"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js":["content.js"],
"css": ["styles.css"]
}
],
"web_accessible_resources": [
"img/icon.jpg"
],
"manifest_version": 2
}
content.js
As a trivial use case prepared a div and added background Image property
var newdiv = document.createElement('div');
newdiv.setAttribute("id", "moot450");
document.body.appendChild(newdiv);
document.getElementById('moot450').style.backgroundImage = "url(" + chrome.extension.getURL('img/icon.jpg') + ")";
styles.css
injected another css for refining injected div
#moot450{
position:absolute;
width:500px;
height:500px;
/*background-image:url(chrome-extension://faaligkhohdchiijdkcokpefpancidoo/img/icon.jpg);*/
}
OUTPUT
Screen shot taken from Google Page after injection
Let me know if you need more information or if it fails.