Firefox Extension - including CSS in manifest.json - css

My manifest is not working when I add CSS into it, while it works in Chrome Extension when I do like that.
Here how my manifest looks:
"css": ["css/jquery-ui.css", "css/font-awesome.css", "css/simplegrid.css", "css/basic.css"],
"js": ["jquery.js", "jquery-ui.js", "myPeaceFile.js"],
myPeaceFile.js works, jquery's are working. But CSS files are not.
I previously asked question about jquery's not working. It looked like this:
"js": ["peace.js", "jquery.js"] - didn't work.
Then I was suggested this and it worked:
"js": ["jquery.js", "peace.js"]
Is it something similar? Please help.
Thanks!

You can attach CSS to pages using Style, in your main.js define a style and attach this style to the contentscript.
var { Style } = require('sdk/stylesheet/style');
var style = Style({
uri: './bootstrap.css'
});
tabs.on('ready', function(tab) {
let worker = tab.attach({
contentScriptFile: [
data.url("jquery.min.js"),
data.url("jquery-ui/jquery-ui.min.js"),
data.url("mycontent-script.js"),
]
});
attach(style, tab);
});
At the Style constructor in the second line you can pass a string, or an array of strings, that represents local URI to stylesheet. In this case the ./bootstrap.css is in the data folder of the extension.

Related

How to solve SvelteKit/Svelte <style> tag with squiggly line not recognising CSS #import

As the title suggests, I have been struggling to find a solution to this squiggly line problem as part of in my Svelte files.
I have looked all over the web and unforturnately I haven't yet being able to find a solution to this error in my VS Code editor.
Please note that despite this error, the imported CSS file is cascading the variables fine and all works fine, however VS Code isn't able to recognise the lang="scss" hence the squiggly line as per screenshot.
NOTE: The imported CSS file is prepended via Svelte's preprocess configs;
Here is a link to the repo holding all the configs and codes;
https://github.com/Untested/demo-svelte
My svelte.config.js (for SvelteKit) has the following and it all resolves well, leaving no squiggles. Note that if you're using vanilla Svelte (not SvelteKit), it may be configured differently.
const config = {
kit: {
adapter: adapter(),
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '#use "src/variables.scss" as *;'
}}},
resolve: {
alias: {
...
}}}
},
preprocess: [
preprocess({
scss: {
prependData: '#use "src/variables.scss" as *;'
},
})
]
};

How does NuxtJS css extraction work for generated static websites?

I am trying to generate a static website out of my (minimal) code with Nuxt. In that code, I integrate in particular the tailwindcss toolkit as well as vue2-leaflet. Upon
nuxt generate
I get two css files, one for the tailwindcss css and the other for the leaflet css. While the former file is fine and contains everything I need, the latter is pretty sparse:
.leaflet-tile-pane{z-index:200}#-webkit-keyframes leaflet-gestures-fadein{to{opacity:1}}#keyframes leaflet-gestures-fadein{0%{opacity:0}to{opacity:1}}
Of course, that makes my map render in a pretty strange way, because most of the css is missing. Here's my current nuxt.config.js:
module.exports = {
mode: 'universal',
head: {
title: pkg.name,
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
css: [
],
plugins: [
{ src: '~plugins/leaflet.js', mode: 'client' }
],
buildModules: [
'#nuxtjs/tailwindcss'
],
modules: ['#nuxtjs/apollo', 'nuxt-purgecss', ['nuxt-i18n', i18n]],
[...]
build: {
extractCSS: true,
}
}
Getting rid of the extractCSS ends up incorporating all the relevant css into the index.html. It works, but then I get the following error:
ERROR Webpack mode only works with build.extractCSS set to *true*. Either extract your CSS or use 'postcss' mode
I'm not sure I understand how that whole css extraction works. Could someone enlighten me? Why is it not working with extractCSS: true? How can I make it work? Why is it working in SPA mode but not in static mode?
You are using nuxt-purgecss which is using purgecss to strip unused CSS.
purgecss do scan HTML (or vue) files for CSS classes in use and then strip unused classes from final CSS bundle.
You can take a look at default purgecss configuration used by nuxt-purgecss here. The paths lists the paths purgecss will scan for CSS usage.
Because you are not using most of the leaflet css directly (in your components), its is necessary to configure purgecss to don't remove leaflet's css.
You can do that by whitelisting (btw not sure if "comment" method will work in Vue\Nuxt)
You can read more here and here
Not tested!!
// nuxt.config.js
{
purgeCSS: {
whitelistPatterns: [/leaflet/, /marker/]
}
}
Regarding the error message
Error message is from nuxt-purgecss module - it is clearly documented here
I don't have deep knowledge of Nuxt build process. So I just assume from the docs that extractCSS: true will use extract-css-chunks-webpack-plugin to extract all CSS to separate CSS file, while (default) extractCSS: false will use PostCSS to extract all CSS and put it directly into the <style> tag of rendered page.
All of that doesn't matter IMHO because the root problem is the use of purgecss and the solution is to configure it correctly to whitelist leaflet CSS classes....

Using browser_action to apply css styling

I am new to chrome extension development. I am writing a chrome extension that will inject CSS into the page. I've been successful in doing this by specifying the css file in manifest.json.
I now want to apply different css (files) depending on a link or button selected on a popup triggered through a browser_action. So clicking link 1 will apply style-red.css and clicking link 2 will apply style-blue.css. A third "reset" button should reset css back to its original state (removing the custom style red or blue css files).
My manifest.json is as follows:
{
"name": "Redesign",
"version": "1.0",
"manifest_version": 2,
"content_scripts": [
{
"matches": ["*://*.my-site.com/*"],
"js": ["jquery-3.1.0.min.js", "script.js"]
}
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs", "*://*.my-site.com/*"
]
}
My current approach is to have a listener in script.js listening for the button pressed in popup.html. Depending on the button pressed, the following script.js will add the corresponding CSS file into my-site.com using the jquery below:
$(document).ready(function() {
var path = chrome.extension.getURL('style-red.css');
$('head').append($('<link>')
.attr("rel","stylesheet")
.attr("type","text/css")
.attr("href", path));
});
I tried to use the above jquery in script.js (without the browser_action in the manifest.json) thinking script.js will get automatically loaded but the CSS does not get applied to my-site.com. What am I doing wrong or is there simpler Javascript without the need for a full jquery library to be added?
And even if the jquery works, how do I apply a different CSS file based on the choice in popup.html as well as reset the css back to its original styling upon user choice?
To insert css file in content scripts, you need to declare the css file as web_accessible_resources
To dynamically insert css files, see chrome.tabs.insertCSS, it can be called in extension context, such as popup page.

With Webpack, is it possible to generate CSS only, excluding the output.js?

I'm using Webpack with the extract-text-webpack-plugin.
In my project, I have some build scripts. One of the build scripts is supposed to bundle and minify CSS only. As I'm using Webpack for the other scripts, I found it a good idea to use Webpack even when I only want to bundle and minify CSS.
It's working fine, except that I can't get rid of the output.js file. I don't want the resulting webpack output file. I just want the CSS for this particular script.
Is there a way to get rid of the resulting JS? If not, do you suggest any other tool specific for handling CSS? Thanks.
There is an easy way, no extra tool is required.
There is an easy way and you don't need extra libraries except which you are already using: webpack with the extract-text-webpack-plugin.
In short:
Make the output js and css file have identical name, then the css file will override js file.
A real example (webpack 2.x):
import path from 'path'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
const config = {
target: 'web',
entry: {
'one': './src/one.css',
'two': './src/two.css'
},
output: {
path: path.join(__dirname, './dist/'),
filename: '[name].css' // output js file name is identical to css file name
},
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin('[name].css') // css file will override generated js file
]
}
Unfortunately, that is currently not possible by design. webpack started as a JavaScript bundler which is capable of handling other "web modules", such as CSS and HTML. JavaScript is chosen as base language, because it can host all the other languages simply as strings. The extract-text-webpack-plugin is just extracting these strings as standalone file (thus the name).
You're probably better off with PostCSS which provides various plugins to post-process CSS effectively.
One solution is to execute webpack with the Node API and control the output with the memory-fs option. Just tell it to ignore the resulting js-file. Set the output.path to "/" in webpackConfig.
var compiler = webpack(webpackConfig);
var mfs = new MemoryFS();
compiler.outputFileSystem = mfs;
compiler.run(function(err, stats) {
if(stats.hasErrors()) { throw(stats.toString()); }
mfs.readdirSync("/").forEach(function (f) {
if(f === ("app.js")) { return; } // ignore js-file
fs.writeFileSync(destination + f, mfs.readFileSync("/" + f));
})
});
You can clean up your dist folder for any unwanted assets after the done is triggered. This can be easily achieved with the event-hooks-webpack-plugin
//
plugins: [
new EventHooksPlugin({
'done': () => {
// delete unwanted assets
}
})
]
Good Luck...

Google Chrome Extensions - Can't load local images with CSS

I have a simple Chrome extension that uses the content script feature to modify a website. More specifically, the background-image of said website.
For some reason I can't seem to be able to use local images, even though they are packed in the extension.
body {
background: #000 url('image.jpg') !important;
background-repeat: repeat !important;
}
That's it, the simplest CSS... but it won't work. The browser doesn't load the image.
Chrome has i18n support that provides the ability to reference your extension in your CSS. I keep my images in an image folder in the extension, so reference assets in the CSS like so:
background-image:url('chrome-extension://__MSG_##extension_id__/images/main.png');
Your image URL should look like chrome-extension://<EXTENSION_ID>/image.jpg
You would be better off replacing css through javascript. From docs:
//Code for displaying <extensionDir>/images/myimage.png:
var imgURL = chrome.extension.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;
There are a lot of older answers and solutions to this question.
As of August 2015 (using Chrome 45 and Manifest version 2), the current "best practice" for linking to local images within Chrome Extensions is the following approach.
1) Link to the asset in your CSS using a relative path to your extension's images folder:
.selector {
background: url('chrome-extension://__MSG_##extension_id__/images/file.png');
}
2) Add the individual asset to to the web_accessible_resources section of your extension's manifest.json file:
"web_accessible_resources": [
"images/file.png"
]
Note: This method is suitable for a few files, but doesn't scale well with many files.
Instead, a better method is to leverage Chrome's support for match patterns to whitelist all files within a given directory:
{
"name": "Example Chrome Extension",
"version": "0.1",
"manifest_version": 2,
...
"web_accessible_resources": [
"images/*"
]
}
Using this approach will allow you to quickly and effortlessly use images in your Chrome Extension's CSS file using natively supported methods.
One option would be to convert your image to base64:
and then put the data right into your css like:
body { background-image: url(data:image/png;base64,iVB...); }
While this might not be an approach you would want to use when regularly developing a webpage, it is a great option due to some of the constraints of building a Chrome Extension.
My solution.
With Menifest v2 you need to add web_accessible_resources to the file and then use chrome-extension://__MSG_##extension_id__/images/pattern.png as the url in your css file.
CSS:
#selector {
background: #fff url('chrome-extension://__MSG_##extension_id__/images/pattern.png');
}
Manifest.json
{
"manifest_version": 2,
"name": "My Extension Name",
"description": "My Description",
"version": "1.0",
"content_scripts": [
{
"matches": ["https://mydomain.com/*"],
"css": ["style.css"]
}
],
"permissions": [
"https://mydomain.com/"
],
"browser_action": {
"default_icon": {
"19": "images/icon19.png",
"38": "images/icon38.png"
},
"default_title": "My Extension Name"
},
"web_accessible_resources": [
"images/pattern.png"
]
}
p.s. Your manifest.json might look different to this one.
This CSS-version-only works in extension environment (app page, popup page, background page, option page) as well as content_scripts CSS file.
In .less file, I always set a variable at the beginning:
#extensionId : ~"__MSG_##extension_id__";
Then later, if you want to refer to extension-local-resource like images, use:
.close{
background-image: url("chrome-extension://#{extensionId}/images/close.png");
}
One thing to mention is that in the web_accessible_resources you can use wildcards. So instead of
"images/pattern.png"
You can use
"images/*"
Just to clarify, according to the documentation, every file in an extension is also accessible by an absolute URL like this:
chrome-extension://<extensionID>/<pathToFile>
Note the <extensionID> is a unique identifier that the extension system generates for each extension. You can see the IDs for all your loaded extensions by going to the URL chrome://extensions. The <pathToFile> is the location of the file under the extension's top folder; it's the same as the relative URL.
...
Changing background image in CSS:
#id { background-image:
url("chrome-extension://<extensionID>/<pathToFile>"); }
Changing background image in CSS through JavaScript:
document.getElementById('id').style.backgroundImage =
"url('chrome-extension://<extensionID>/<pathToFile>')");
Changing background image in CSS through jQuery:
$("#id").css("background-image",
"url('chrome-extension://<extensionID>/<pathToFile>')");
For manifest v3, there are some modifications:
chrome.extension.getUrl() -> chrome.runtime.getUrl()
"web_accessible_resources" -> "web_accessible_resources.resources"
fill in "web_accessible_resources.matches"
2, 3 like this:
"web_accessible_resources": [{
"resources": ["images/logo.png"],
"matches": ["<all_urls>"],
}],
reference:
https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/#web-accessible-resources
Those answers above are great but your extension gets a new id every time it gets installed, so putting the id manually doesn't work if you gonna make it public at some point.
Here's my solution using manifest v.3:
//Get the url from some file within your extension's folder and store it on a global variable
var url = chrome.runtime.getURL('my_extension/img/Icon.svg');
//Take off the last part from the url string
url = url.replace('img/Icon.svg', '');
Now replace the src attribute for a custom one on every img tag and keep the file path as it's value like this:
<img ref-file="img/IconStop.svg" alt="">
Then run this function after loading the html:
loadImgs = function () {
$("img[ref-file]").each(function() {
var ref_file = $(this).attr('ref-file');
url = url + ref_file;
$(this).attr('src', url);
});
}

Resources