Comments (5)
Here are some notes about importing in background.js
in Firefox. Mozilla's docs should explain how to get this working, but they don't.
For context, Stardown uses Firefox manifest v2 because of this bug: 1851083 - Manifest V3 extensions with activeTab/tabs permission require user interaction not previously required, showing blue dot on desktop and no indicator on Android.
I created common.js
and defined this function:
export async function getSetting(name, default_) {
...
}
In background.js
, I added import { getSetting } from './common.js';
to the top and removed the getSetting
definition.
Loading the extension gives the error Uncaught SyntaxError: import declarations may only appear at top level of a module
.
I made background.js
a module by adding "type": "module"
to manifest.json
:
"background": {
"scripts": [
"background.js",
"common.js"
],
"type": "module"
},
This changes the error message to Tried to get undefined setting "doubleClickInterval"
, which is printed when getSetting
's await browser.storage.sync.get
call returns undefined
. This happens because currently, when Stardown loads, it immediately calls getSetting('doubleClickInterval', 500).then(value => doubleClickInterval = value)
.
Wrapping the getSetting
call with browser.runtime.onInstalled.addListener(() => { ... });
doesn't fix the error or change the error message. Neither does using the code below in place of import { getSetting } from './common.js';
and the top-level getSetting
call.
let getSetting;
import('./common.js').then((exports) => {
getSetting = exports['getSetting'];
getSetting('doubleClickInterval', 500).then(value => doubleClickInterval = value);
});
Neither does replacing "type": "module"
in manifest.json
with "page": "background.html"
and using this HTML in background.html
:
<!DOCTYPE html>
<html>
<body>
<script type="module" src='./background.js'></script>
</body>
</html>
Neither does using both "type": "module"
and "page": "background.html"
in manifest.json
.
I put "type": "module"
back in manifest.json
and removed "page": "background.html"
.
When I comment out getSetting('doubleClickInterval', 500).then(value => doubleClickInterval = value);
, the extension loads with no errors. However, clicking the extension's icon gives the error Error: No response received from the content script
.
Uncommenting the getSetting
call, removing import { getSetting } from './common.js';
, removing export
, and removing "type": "module"
also gives the error Error: No response received from the content script
.
Using this in manifest.json
:
"background": {
"page": "background.html"
},
and this background.html
:
<!DOCTYPE html>
<html>
<body>
<script type="module" src='./common.js'></script>
<script type="module" src='./background.js'></script>
</body>
</html>
with the import
and export
keywords gives the error Tried to get undefined setting "doubleClickInterval"
. Without them gives Uncaught ReferenceError: getSetting is not defined
.
Removing both instances of type="module"
from the HTML above (and still not using import
or export
allows the extension to mostly work in Firefox! However, clicking the extension's icon now displays some Mojibake instead of a check, and Chromium probably requires unconditional use of import
and export
.
Maybe Firefox manifest v2 doesn't allow the use of import
and export
? Their documentation is missing something. We should probably just use a bundler.
One of the sources I looked at for ideas: [WebExtension] Import a module in a script
from stardown.
About the problem with Chrome giving us the error message Uncaught SyntaxError: Cannot use import statement outside a module
from content.js:17, I tried enabling Chrome's verbose logging with chrome.exe --enable-logging --v=1
(looks like the Linux equivalent might be google-chrome --enable-logging --v=1
), but the logs don't seem to have anything helpful. I'm putting the relevant parts of the logs below anyways. My local test copy of Stardown has the Chrome extension ID ckghjmcmjkaefnkmobodopfihgkeehno
. The .cc
files mentioned don't appear to be in the https://github.com/chromium/chromium repo. I was surprised to see Chrome search for manifest files in folders Stardown/chrome
and Stardown/chromium
since Stardown hasn't had those folders for a while.
Chrome version 125.0.6422.142
...
[6764:6656:0607/204034.346:VERBOSE1:script_context.cc(149)] Created context:
extension id: ckghjmcmjkaefnkmobodopfihgkeehno
frame: 0000000000000000
URL:
context_type: BLESSED_EXTENSION
effective extension id: ckghjmcmjkaefnkmobodopfihgkeehno
effective context type: BLESSED_EXTENSION
[6764:6656:0607/204034.347:VERBOSE1:script_context.cc(149)] Created context:
extension id: (none)
frame: 0000000000000000
URL:
context_type: UNSPECIFIED
effective extension id: (none)
effective context type: UNSPECIFIED
...
[8796:6160:0607/204040.099:VERBOSE1:script_context.cc(149)] Created context:
extension id: ckghjmcmjkaefnkmobodopfihgkeehno
frame: 00001FF10014E540
URL:
context_type: CONTENT_SCRIPT
effective extension id: ckghjmcmjkaefnkmobodopfihgkeehno
effective context type: CONTENT_SCRIPT
[8796:6160:0607/204040.099:VERBOSE1:script_context.cc(149)] Created context:
extension id: (none)
frame: 0000000000000000
URL:
context_type: UNSPECIFIED
effective extension id: (none)
effective context type: UNSPECIFIED
[8796:6160:0607/204040.100:VERBOSE1:dispatcher.cc(419)] Num tracked contexts: 3
[8476:22148:0607/204040.119:INFO:CONSOLE(17)] "Uncaught SyntaxError: Cannot use import statement outside a module", source: chrome-extension://ckghjmcmjkaefnkmobodopfihgkeehno/content.js (17)
...
[8476:22148:0607/204025.928:WARNING:load_error_reporter.cc(72)] Extension error: Failed to load extension from: C:\Users\chris\Documents\programming\Stardown\chrome. Manifest file is missing or unreadable
[8476:22148:0607/204025.930:WARNING:load_error_reporter.cc(72)] Extension error: Failed to load extension from: C:\Users\chris\Documents\programming\Stardown\chromium. Manifest file is missing or unreadable
...
[6764:6656:0607/204434.453:VERBOSE1:script_context.cc(162)] Destroyed context for extension
extension id: ckghjmcmjkaefnkmobodopfihgkeehno
effective extension id: ckghjmcmjkaefnkmobodopfihgkeehno
[6764:6656:0607/204434.453:VERBOSE1:script_context.cc(162)] Destroyed context for extension
extension id:
effective extension id:
from stardown.
Continuing with trying to fix Chrome's Uncaught SyntaxError: Cannot use import statement outside a module
, I tried temporarily moving all of Stardown's content code into content.js so that it doesn't use import
. It worked fine, as expected. Then I created a file called browser.js with export const browser = chrome;
and added one import to content.js: import { browser } from './browser.js';
. It still gave the same error message as before both with and without "type": "module"
in manifest.json in the content_scripts
object. When I added "browser.js"
to the list of content scripts in manifest.json, the same error message appeared as well as Uncaught SyntaxError: Unexpected token 'export'
from browser.js, again both with and without "type": "module"
.
I repeated all of these steps again with the urlEncode
function instead of the browser
variable and got all the same results.
Not even the most simple cases of importing and exporting are working for Chrome content scripts. We may need to use a bundler for Chrome as well.
from stardown.
From javascript - How to import ES6 modules in content script for Chrome Extension - Stack Overflow, many people don't expect to be able to use or need import and export statements in content scripts. Apparently, content scripts are all loaded together in the order listed in the manifest as if they're one big file. However, some of Stardown's code used in the content is also used in the background, so it's not an easy choice to just remove the import
s and export
s. The linked discussion also talks about a function named import
. I tried it and it works for the simple cases. I'll do a more thorough test with it soon. I wonder if it can work for the background scripts, and for Firefox. One obvious downside is that since it uses browser
, that variable will need to be defined in almost every file instead of being defined in one and imported into the others.
from stardown.
Here is Stardown's current file structure:
flowchart TD
menu.js --> chromiumConfig.js
menu.js --> firefoxConfig.js
common.js --> md.js
chromiumConfig.js --> content.js
firefoxConfig.js --> content.js
common.js --> content.js
md.js --> content.js
createTextFragmentArg.js --> content.js
chromiumConfig.js --> background.js
firefoxConfig.js --> background.js
common.js --> background.js
md.js --> background.js
common.js --> options.js
I don't see a way to change this so that it has no files that both import and export, unless we go back to using something like if (browserName === 'chromium')
in many places and/or having repeated code.
@chizuo Changing Stardown to not use both import
and export
in any content files didn't fix the error we've been getting (more details in an earlier comment here), and to avoid (or at least minimize) repeated code and if/else statements determining which browser the code is running in, Stardown requires having some files that both import and export.
Using the import
function instead of the keyword and defining browser
in many places works in simple cases. Here's a better way to use the import
function than what I tried before:
let menu;
(async () => {
menu = await import(browser.runtime.getURL('./menu.js'));
})();
However, our use case is not simple enough for the import
function; it gives the error message Uncaught (in promise) TypeError: import() is disallowed on ServiceWorkerGlobalScope by the HTML specification. See https://github.com/w3c/ServiceWorker/issues/1356.
This error sounds like it could be fixed by using the import
function for the content and the import
keyword for the background, but as you can see in the diagram, the config files and md.js need to be used by both the content and the background, and they all need to import unless we have repeated code. We can't conditionally use one import or the other because An import declaration can only be used at the top level of a module
.
It looks like we might have no choice but to use a bundler for Chrome.
from stardown.
Related Issues (20)
- Show a different context menu option depending on the context HOT 4
- Create markdown when hovering over image
- Add a setting for selection copying to result in markdown that tries to keep the same format
- Copy tables as markdown
- Show a notification when copying fails
- Attempt to combine the Firefox and Chromium versions
- Settings that require permissions have a delay
- Newline characters in selections can appear in link titles
- Add support for Safari HOT 1
- Keep emphasis when creating block quotes
- Keep bold style when creating block quotes
- Text fragment generation timeout prevents write to clipboard, and the success indicator is still shown
- Keep selected block quotes when creating block quotes
- Block quote output should contain any selected images
- Markdown of videos HOT 4
- Markdown of YouTube videos from Chrome doesn't render well in Obsidian
- Firefox context menu item creation should only happen on installation
- The right-click option naively appends HTML element IDs and/or text fragments to the URL
- Generalize messaging from background scripts to content scripts
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from stardown.