From 1f7445355a7111162341cf84fe486cdce81dfd7f Mon Sep 17 00:00:00 2001 From: Adam Pritchard Date: Fri, 27 Sep 2024 21:44:26 -0400 Subject: [PATCH 1/6] MV3 nominally works in Chrome --- src/chrome/backgroundscript.js | 98 ++++++++++++++++++-------- src/common/common-logic.js | 10 +-- src/common/options.js | 2 +- src/common/test/utils-test.js | 40 +++++------ src/common/utils.js | 122 ++++++++++----------------------- src/manifest.json | 13 ++-- utils/build.js | 2 +- 7 files changed, 142 insertions(+), 145 deletions(-) diff --git a/src/chrome/backgroundscript.js b/src/chrome/backgroundscript.js index 9c1c4372..b077cbcd 100644 --- a/src/chrome/backgroundscript.js +++ b/src/chrome/backgroundscript.js @@ -8,20 +8,59 @@ marked:false, hljs:false, Utils:false, CommonLogic:false */ /*jshint devel:true, browser:true*/ -/* - * Chrome background script. - */ +if (typeof browser === "undefined") { + // Chrome does not support the browser namespace yet. + // See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/background + globalThis.browser = chrome; +} -// On each load, check if we should show the options/changelist page. -function onLoad() { - // This timeout is a dirty hack to fix bug #119: "Markdown Here Upgrade - // Notification every time I open Chrome". That issue on Github for details. - // https://github.com/adam-p/markdown-here/issues/119 - window.setTimeout(upgradeCheck, 30000); +// We supply a #hash to the background page, so that we know when we're +// loaded via `background.page` (manifest V2 and Firefox manifest V3) vs +// `background.service_worker` (manifest V3 in Chrome and Safari). +var backgroundPage = !!location.hash; + +if (!backgroundPage) { + // When loaded via a background page, the support scripts are already + // present. When loaded via a service worker, we need to import them. + // (`importScripts` is only available in service workers.) + importScripts('../common/utils.js'); + importScripts('../common/common-logic.js'); + importScripts('../common/marked.js'); + importScripts('../common/highlightjs/highlight.js'); + importScripts('../common/markdown-render.js'); + importScripts('../common/options-store.js'); } -// In the interest of improved browser load performace, call `onLoad` after a tick. -window.addEventListener('load', Utils.nextTickFn(onLoad), false); +// Note that this file is both the script for a background page _and_ for a service +// worker. The way these things work are quite different, and we must be cognizant of that +// while writing this file. +// +// The key difference is that a background page is loaded once per browser session; a +// service worker is loaded when extension-related events occur, and then is torn down +// after 30 seconds of inactivity (with lifecycle caveats). This means that we can't rely +// on global variables to store state, and we must be mindful about how we handle +// messages. + +// For the background page, this listener is added once and remains active for the browser +// session; for the service worker, this listener is added every time the service worker +// is loaded, and is torn down when the service worker is torn down. +chrome.runtime.onInstalled.addListener((details) => { + if (details.reason !== 'install' && details.reason !== 'update') { + return; + } + + // Create the context menu that will signal our main code. + // This must be called only once, when installed or updated, so we do it here. + chrome.contextMenus.create({ + id: 'markdown-here-context-menu', + contexts: ['editable'], + title: Utils.getMessage('context_menu_item') + }); + + // Note: If we find that the upgrade info page opens too often, we may + // need to add delays. See: https://github.com/adam-p/markdown-here/issues/119 + upgradeCheck(); +}); function upgradeCheck() { OptionsStore.get(function(options) { @@ -35,7 +74,7 @@ function upgradeCheck() { OptionsStore.set({ 'last-version': appManifest.version }, function() { // This is the very first time the extensions has been run, so show the // options page. - chrome.tabs.create({ url: chrome.extension.getURL(optionsURL) }); + chrome.tabs.create({ url: chrome.runtime.getURL(optionsURL) }); }); } else if (options['last-version'] !== appManifest.version) { @@ -45,23 +84,20 @@ function upgradeCheck() { // The extension has been newly updated optionsURL += '?prevVer=' + options['last-version']; - showUpgradeNotification(chrome.extension.getURL(optionsURL)); + showUpgradeNotification(chrome.runtime.getURL(optionsURL)); }); } }); } -// Create the context menu that will signal our main code. -chrome.contextMenus.create({ - contexts: ['editable'], - title: Utils.getMessage('context_menu_item'), - onclick: function(info, tab) { - chrome.tabs.sendMessage(tab.id, {action: 'context-click'}); - } +// Handle context menu clicks. +chrome.contextMenus.onClicked.addListener(function(info, tab) { + chrome.tabs.sendMessage(tab.id, {action: 'context-click'}); }); -// Handle rendering requests from the content script. -// See the comment in markdown-render.js for why we do this. +// Handle rendering requests from the content script. Note that incoming messages will +// revive the service worker, then process the message, then tear down the service worker. +// See the comment in markdown-render.js for why we use these requests. chrome.runtime.onMessage.addListener(function(request, sender, responseCallback) { // The content script can load in a not-real tab (like the search box), which // has an invalid `sender.tab` value. We should just ignore these pages. @@ -89,11 +125,11 @@ chrome.runtime.onMessage.addListener(function(request, sender, responseCallback) } else if (request.action === 'show-toggle-button') { if (request.show) { - chrome.browserAction.enable(sender.tab.id); - chrome.browserAction.setTitle({ + chrome.action.enable(sender.tab.id); + chrome.action.setTitle({ title: Utils.getMessage('toggle_button_tooltip'), tabId: sender.tab.id }); - chrome.browserAction.setIcon({ + chrome.action.setIcon({ path: { "16": Utils.getLocalURL('/common/images/icon16-button-monochrome.png'), "19": Utils.getLocalURL('/common/images/icon19-button-monochrome.png'), @@ -105,11 +141,11 @@ chrome.runtime.onMessage.addListener(function(request, sender, responseCallback) return false; } else { - chrome.browserAction.disable(sender.tab.id); - chrome.browserAction.setTitle({ + chrome.action.disable(sender.tab.id); + chrome.action.setTitle({ title: Utils.getMessage('toggle_button_tooltip_disabled'), tabId: sender.tab.id }); - chrome.browserAction.setIcon({ + chrome.action.setIcon({ path: { "16": Utils.getLocalURL('/common/images/icon16-button-disabled.png'), "19": Utils.getLocalURL('/common/images/icon19-button-disabled.png'), @@ -148,7 +184,7 @@ chrome.runtime.onMessage.addListener(function(request, sender, responseCallback) }); // Add the browserAction (the button in the browser toolbar) listener. -chrome.browserAction.onClicked.addListener(function(tab) { +chrome.action.onClicked.addListener(function(tab) { chrome.tabs.sendMessage(tab.id, {action: 'button-click', }); }); @@ -191,6 +227,10 @@ function showUpgradeNotification(optionsURL) { }); }; + // TODO: This interval won't keep the service worker alive, so if a content script + // doesn't reload in about 30 seconds, we'll lose the interval and the notification + // won't show. + // Maybe use the Alarms API? Maybe restructure this so that it's less hacky? showUpgradeNotificationInterval = setInterval(askTabsToShowNotification, 5000); }); } diff --git a/src/common/common-logic.js b/src/common/common-logic.js index 378cb6e4..69ac5bde 100644 --- a/src/common/common-logic.js +++ b/src/common/common-logic.js @@ -38,11 +38,12 @@ function getUpgradeNotification(optionsURL, responseCallback) { Utils.getLocalFile( Utils.getLocalURL('/common/upgrade-notification.html'), - 'text/html', + 'text', function(html) { // Get the logo image data - Utils.getLocalFileAsBase64( + Utils.getLocalFile( Utils.getLocalURL('/common/images/icon32.png'), + 'base64', function(logoBase64) { // Do some rough template replacement html = html.replace('{{optionsURL}}', optionsURL) @@ -72,7 +73,7 @@ function getForgotToRenderPromptContent(responseCallback) { Utils.getLocalFile( Utils.getLocalURL('/common/forgot-to-render-prompt.html'), - 'text/html', + 'text', function(html) { html = html.replace('{{forgot_to_render_prompt_title}}', Utils.getMessage('forgot_to_render_prompt_title')) .replace('{{forgot_to_render_prompt_info}}', Utils.getMessage('forgot_to_render_prompt_info')) @@ -82,8 +83,9 @@ function getForgotToRenderPromptContent(responseCallback) { .replace('{{forgot_to_render_send_button}}', Utils.getMessage('forgot_to_render_send_button')); // Get the logo image data - Utils.getLocalFileAsBase64( + Utils.getLocalFile( Utils.getLocalURL('/common/images/icon48.png'), + 'base64', function(logoBase64) { // Do some rough template replacement html = html.replace('{{logoBase64}}', logoBase64); diff --git a/src/common/options.js b/src/common/options.js index 05e9e920..aa113175 100644 --- a/src/common/options.js +++ b/src/common/options.js @@ -120,7 +120,7 @@ function onLoad() { // of extension packages. // Check if our test file exists. - Utils.getLocalFile('./test/index.html', 'text/html', function(_, err) { + Utils.getLocalFile('./test/index.html', 'text', function(_, err) { // The test files aren't present, so hide the button. if (err) { // The test files aren't present, so hide the button. diff --git a/src/common/test/utils-test.js b/src/common/test/utils-test.js index c8ce4016..433810f3 100644 --- a/src/common/test/utils-test.js +++ b/src/common/test/utils-test.js @@ -245,38 +245,27 @@ describe('Utils', function() { describe('getLocalFile', function() { - it('should return correct data', function(done) { - // We "know" our logo file starts with this string when base64'd + it('should return correct text data', function(done) { var KNOWN_PREFIX = ''; var callback = function(data) { expect(data.slice(0, KNOWN_PREFIX.length)).to.equal(KNOWN_PREFIX); done(); }; - Utils.getLocalFile('../options.html', 'text/html', callback); + Utils.getLocalFile('../options.html', 'text', callback); }); - it('should correctly handle absence of optional argument', function(done) { - // We "know" our options.html file starts with this string - var KNOWN_PREFIX = ''; + it('should return correct json data', function(done) { var callback = function(data) { - expect(data.slice(0, KNOWN_PREFIX.length)).to.equal(KNOWN_PREFIX); + expect(data).to.be.an('object'); + expect(data).to.have.property('app_name'); done(); }; - Utils.getLocalFile('../options.html', callback); + Utils.getLocalFile('/_locales/en/messages.json', 'json', callback); }); - it('should supply an error arg to callback if file not found', function(done) { - Utils.getLocalFile('badfilename', function(val, err) { - expect(err).to.be.ok; - done(); - }); - }); - }); - - describe('getLocalFileAsBase64', function() { - it('should return data as Base64', function(done) { + it('should return correct base64 data', function(done) { // We "know" our logo file starts with this string when base64'd var KNOWN_PREFIX = 'iVBORw0KGgo'; var callback = function(data) { @@ -284,12 +273,21 @@ describe('Utils', function() { done(); }; - Utils.getLocalFileAsBase64('../images/icon16.png', callback); + Utils.getLocalFile('../images/icon16.png', 'base64', callback); }); it('should supply an error arg to callback if file not found', function(done) { - Utils.getLocalFile('badfilename', function(val, err) { + Utils.getLocalFile('badfilename', 'text', function(val, err) { + expect(err).to.be.ok; + expect(val).to.not.be.ok; + done(); + }); + }); + + it('should supply an error arg to callback if dataType is bad', function(done) { + Utils.getLocalFile('../options.html', 'nope', function(val, err) { expect(err).to.be.ok; + expect(val).to.not.be.ok; done(); }); }); @@ -309,7 +307,7 @@ describe('Utils', function() { }; var url = Utils.getLocalURL('/common/options.html'); - Utils.getLocalFile(url, 'text/html', callback); + Utils.getLocalFile(url, 'text', callback); }); }); diff --git a/src/common/utils.js b/src/common/utils.js index 46dae091..1f3a9f6d 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -303,7 +303,7 @@ function getLocalURL(url) { /*? if (platform==='chrome' || platform==='firefox') { */ if (typeof(chrome) !== 'undefined') { matched = true; - return chrome.extension.getURL(url); + return chrome.runtime.getURL(url); } /*? } */ /*? if (platform==='safari') { */ @@ -337,90 +337,45 @@ function getLocalURL(url) { // Makes an asynchrous XHR request for a local file (basically a thin wrapper). -// `mimetype` is optional. `callback` will be called with the responseText as +// `dataType` must be one of 'text', 'json', or 'base64'. +// `callback` will be called with the responseText as // argument. // If error occurs, `callback`'s second parameter will be an error. -function getLocalFile(url, mimetype, callback) { - if (!callback) { - // optional mimetype not provided - callback = mimetype; - mimetype = null; - } - - var xhr = new window.XMLHttpRequest(); - if (mimetype) { - xhr.overrideMimeType(mimetype); - } - xhr.open('GET', url); - - xhr.onload = function() { - if (callback) { - callback(this.responseText); - callback = null; - } - }; - - xhr.onerror = function(e) { - if (callback) { - callback(null, e); - callback = null; - } - }; - - try { - // On some platforms, xhr.send throws an error if the url is not found. - // On some platforms, it will call onerror and on some it won't. - xhr.send(); - } - catch(e) { - if (callback) { - callback(null, e); - callback = null; - return; - } - } -} - - -// Does async XHR request to get data at `url`, then passes it to `callback` -// Base64-encoded. -// Intended to be used get the logo image file in a form that can be put in a -// data-url image element. -// If error occurs, `callback`'s second parameter will be an error. -function getLocalFileAsBase64(url, callback) { - var xhr = new window.XMLHttpRequest(); - xhr.open('GET', url); - xhr.responseType = 'arraybuffer'; - - xhr.onload = function() { - var uInt8Array = new Uint8Array(this.response); - var base64Data = base64EncArr(uInt8Array); - - if (callback) { - callback(base64Data); - callback = null; - } - }; - - xhr.onerror = function(e) { - if (callback) { - callback(null, e); - callback = null; - } - }; +function getLocalFile(url, dataType, callback) { + fetch(url) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error status: ${response.status}`); + } - try { - // On some platforms, xhr.send throws an error if the url is not found. - // On some platforms, it will call onerror and on some it won't. - xhr.send(); - } - catch(e) { - if (callback) { - callback(null, e); - callback = null; - return; - } - } + switch (dataType) { + case 'text': + return response.text(); + case 'json': + return response.json(); + case 'base64': + return response.blob(); + default: + throw new Error(`Unknown dataType: ${dataType}`); + } + }) + .then(data => { + switch (dataType) { + case 'text': + case 'json': + callback(data); + break; + case 'base64': + data.arrayBuffer().then(function(buffer) { + var uInt8Array = new Uint8Array(buffer); + var base64Data = base64EncArr(uInt8Array); + callback(base64Data); + }); + } + }) + .catch(err => { + callback(null, err); + }); } @@ -945,7 +900,7 @@ function getSafariStringBundle(callback) { function getStringBundle(locale, callback) { var url = getLocalURL('/_locales/' + locale + '/messages.json'); - getLocalFile(url, 'application/json', function(data, err) { + getLocalFile(url, 'json', function(data, err) { if (err) { return callback(null, err); } @@ -1242,7 +1197,6 @@ Utils.getDocumentFragmentHTML = getDocumentFragmentHTML; Utils.isElementDescendant = isElementDescendant; Utils.getLocalURL = getLocalURL; Utils.getLocalFile = getLocalFile; -Utils.getLocalFileAsBase64 = getLocalFileAsBase64; Utils.fireMouseClick = fireMouseClick; Utils.MARKDOWN_HERE_EVENT = MARKDOWN_HERE_EVENT; Utils.makeRequestToPrivilegedScript = makeRequestToPrivilegedScript; diff --git a/src/manifest.json b/src/manifest.json index f3c5af49..2116dbc8 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,9 +1,9 @@ { - "manifest_version": 2, + "manifest_version": 3, "name": "__MSG_app_name__", "version": "2.13.4", "description": "__MSG_app_slogan__", - "homepage_url": "http://markdown-here.com", + "homepage_url": "https://markdown-here.com", "default_locale": "en", "icons": { "16": "common/images/icon16.png", @@ -13,7 +13,10 @@ "512": "common/images/icon512.png" }, "permissions": ["contextMenus", "storage"], - "background": {"page": "chrome/background.html"}, + "background": { + "page": "chrome/background.html#background-page", + "service_worker": "chrome/backgroundscript.js" + }, "content_scripts": [ { "matches": ["http://*/*", "https://*/*"], @@ -28,7 +31,7 @@ ] } ], - "browser_action": { + "action": { "default_icon": { "16": "common/images/icon16-button-monochrome.png", "19": "common/images/icon19-button-monochrome.png", @@ -44,7 +47,7 @@ "open_in_tab": true } - ,"applications": { + ,"browser_specific_settings": { "gecko": { "id": "markdown-here-webext@adam.pritchard" } diff --git a/utils/build.js b/utils/build.js index 9274aab3..8844999d 100644 --- a/utils/build.js +++ b/utils/build.js @@ -71,7 +71,7 @@ function addBuildFile(platformName, zip, fullPath, zipPath) { else if (platformName === CHROME_PLATFORM && manifestJsonFileRegex.test(fullPath)) { // Remove the Firefox-specific stuff from manifest.json when building for Chrome. fileContents = fs.readFileSync(fullPath, {encoding: 'utf8'}); - fileContents = fileContents.replace(/,"applications":[^{]*{[^{]*{[^}]*}[^}]*}/m, ''); + fileContents = fileContents.replace(/,"browser_specific_settings":[^{]*{[^{]*{[^}]*}[^}]*}/m, ''); zip.append(fileContents, { name: zipPath }); } else { From dd3da2502292a88d61cfac90fc5b87cd13b0ffc9 Mon Sep 17 00:00:00 2001 From: Adam Pritchard Date: Mon, 30 Sep 2024 19:51:23 -0400 Subject: [PATCH 2/6] remove all uses of XHR; rework getLocalFile The service worker background doesn't allow XHR reqs, so replace with `fetch`. Also expanded use of `getLocalFile` so that it's used for all(ish) local file requests (rather than sometimes using XHR/fetch). --- src/common/options-store.js | 40 ++++++---------- src/common/options.js | 66 +++++++++------------------ src/common/test/options-store-test.js | 17 ++----- src/common/test/utils-test.js | 22 +++++++-- src/common/utils.js | 26 +++-------- 5 files changed, 66 insertions(+), 105 deletions(-) diff --git a/src/common/options-store.js b/src/common/options-store.js index 1df85b05..0ebe6c75 100644 --- a/src/common/options-store.js +++ b/src/common/options-store.js @@ -122,8 +122,8 @@ var ChromeOptionsStore = { // The default values or URLs for our various options. defaults: { - 'main-css': {'__defaultFromFile__': '/common/default.css', '__mimeType__': 'text/css'}, - 'syntax-css': {'__defaultFromFile__': '/common/highlightjs/styles/github.css', '__mimeType__': 'text/css'}, + 'main-css': {'__defaultFromFile__': '/common/default.css', '__dataType__': 'text'}, + 'syntax-css': {'__defaultFromFile__': '/common/highlightjs/styles/github.css', '__dataType__': 'text'}, 'math-enabled': DEFAULTS['math-enabled'], 'math-value': DEFAULTS['math-value'], 'hotkey': DEFAULTS['hotkey'], @@ -286,8 +286,8 @@ var MozillaOptionsStore = { // The default values or URLs for our various options. defaults: { 'local-first-run': true, - 'main-css': {'__defaultFromFile__': 'resource://markdown_here_common/default.css', '__mimeType__': 'text/css'}, - 'syntax-css': {'__defaultFromFile__': 'resource://markdown_here_common/highlightjs/styles/github.css', '__mimeType__': 'text/css'}, + 'main-css': {'__defaultFromFile__': 'resource://markdown_here_common/default.css', '__dataType__': 'text/css'}, + 'syntax-css': {'__defaultFromFile__': 'resource://markdown_here_common/highlightjs/styles/github.css', '__dataType__': 'text/css'}, 'math-enabled': DEFAULTS['math-enabled'], 'math-value': DEFAULTS['math-value'], 'hotkey': DEFAULTS['hotkey'], @@ -461,8 +461,8 @@ var SafariOptionsStore = { // The default values or URLs for our various options. defaults: { - 'main-css': {'__defaultFromFile__': (typeof(safari) !== 'undefined' ? safari.extension.baseURI : '')+'markdown-here/src/common/default.css', '__mimeType__': 'text/css'}, - 'syntax-css': {'__defaultFromFile__': (typeof(safari) !== 'undefined' ? safari.extension.baseURI : '')+'markdown-here/src/common/highlightjs/styles/github.css', '__mimeType__': 'text/css'}, + 'main-css': {'__defaultFromFile__': (typeof(safari) !== 'undefined' ? safari.extension.baseURI : '')+'markdown-here/src/common/default.css', '__dataType__': 'text/css'}, + 'syntax-css': {'__defaultFromFile__': (typeof(safari) !== 'undefined' ? safari.extension.baseURI : '')+'markdown-here/src/common/highlightjs/styles/github.css', '__dataType__': 'text/css'}, 'math-enabled': DEFAULTS['math-enabled'], 'math-value': DEFAULTS['math-value'], 'hotkey': DEFAULTS['hotkey'], @@ -524,31 +524,19 @@ this.OptionsStore._fillDefaults = function(prefsObj, callback) { } // This function may be asynchronous (if XHR occurs) or it may be a straight - // recursion. + // synchronous callback invocation. function doDefaultForKey(key, callback) { // Only take action if the key doesn't already have a value set. if (typeof(prefsObj[key]) === 'undefined') { if (that.defaults[key].hasOwnProperty('__defaultFromFile__')) { - var xhr = new window.XMLHttpRequest(); - - if (that.defaults[key]['__mimeType__']) { - xhr.overrideMimeType(that.defaults[key]['__mimeType__']); - } - - // Get the default value from the indicated file. - xhr.open('GET', that.defaults[key]['__defaultFromFile__']); - - xhr.onreadystatechange = function() { - if (this.readyState === this.DONE) { - // Assume 200 OK -- it's just a local call - prefsObj[key] = this.responseText; - + Utils.getLocalFile( + that.defaults[key]['__defaultFromFile__'], + that.defaults[key]['__dataType__'] || 'text', + function(data) { + prefsObj[key] = data; callback(); - return; - } - }; - - xhr.send(); + }); + return; } else { // Set the default. diff --git a/src/common/options.js b/src/common/options.js index aa113175..b804d380 100644 --- a/src/common/options.js +++ b/src/common/options.js @@ -47,14 +47,10 @@ function onLoad() { // // Get the available highlight.js styles. - xhr = new XMLHttpRequest(); - xhr.overrideMimeType('application/json'); - xhr.open('GET', 'highlightjs/styles/styles.json'); - xhr.onreadystatechange = function() { - if (this.readyState === this.DONE) { - // Assume 200 OK -- it's just a local call - var syntaxStyles = JSON.parse(this.responseText); - + Utils.getLocalFile( + Utils.getLocalURL('/common/highlightjs/styles/styles.json'), + 'json', + function(syntaxStyles) { for (var name in syntaxStyles) { cssSyntaxSelect.options.add(new Option(name, syntaxStyles[name])); } @@ -63,9 +59,7 @@ function onLoad() { cssSyntaxSelect.selectedIndex = cssSyntaxSelect.options.length - 1; cssSyntaxSelect.addEventListener('change', cssSyntaxSelectChange); - } - }; - xhr.send(); + }); // // Restore previously set options (asynchronously) @@ -353,16 +347,12 @@ document.querySelector('#markdown-toggle-button').addEventListener('click', mark // Reset the main CSS to default. function resetCssEdit() { // Get the default value. - var xhr = new XMLHttpRequest(); - xhr.overrideMimeType(OptionsStore.defaults['main-css']['__mimeType__']); - xhr.open('GET', OptionsStore.defaults['main-css']['__defaultFromFile__']); - xhr.onreadystatechange = function() { - if (this.readyState === this.DONE) { - // Assume 200 OK -- it's just a local call - cssEdit.value = this.responseText; - } - }; - xhr.send(); + Utils.getLocalFile( + OptionsStore.defaults['main-css']['__defaultFromFile__'], + OptionsStore.defaults['main-css']['__dataType__'], + function(defaultValue) { + cssEdit.value = defaultValue; + }); } document.getElementById('reset-button').addEventListener('click', resetCssEdit, false); @@ -381,29 +371,19 @@ function cssSyntaxSelectChange() { } // Get the CSS for the selected theme. - var xhr = new XMLHttpRequest(); - xhr.overrideMimeType('text/css'); - xhr.open('GET', 'highlightjs/styles/'+selected); - xhr.onreadystatechange = function() { - if (this.readyState === this.DONE) { - // Assume 200 OK -- it's just a local call - cssSyntaxEdit.value = this.responseText; - } - }; - xhr.send(); + Utils.getLocalFile( + Utils.getLocalURL('/common/highlightjs/styles/'+selected), + 'text', + css => { + cssSyntaxEdit.value = css; + }); } function loadChangelist() { - var xhr = new XMLHttpRequest(); - xhr.overrideMimeType('text/plain'); - - // Get the changelist from a local file. - xhr.open('GET', 'CHANGES.md'); - xhr.onreadystatechange = function() { - if (this.readyState === this.DONE) { - // Assume 200 OK -- it's just a local call - var changes = this.responseText; - + Utils.getLocalFile( + Utils.getLocalURL('/common/CHANGES.md'), + 'text', + function(changes) { var markedOptions = { gfm: true, pedantic: false, @@ -426,9 +406,7 @@ function loadChangelist() { // Move the changelist section up in the page $('#changelist-container').insertAfter('#pagehead'); } - } - }; - xhr.send(); + }); } // Choose one of the donate pleas to use, and update the donate info so we can diff --git a/src/common/test/options-store-test.js b/src/common/test/options-store-test.js index e128f99e..6ebd008e 100644 --- a/src/common/test/options-store-test.js +++ b/src/common/test/options-store-test.js @@ -227,22 +227,15 @@ describe('OptionsStore', function() { // Set a default value that requires a XHR OptionsStore.defaults[testKeys[0]] = {'__defaultFromFile__': window.location.href}; - // Note: Using $.ajax won't work because for local requests Firefox sets - // status to 0 even on success. jQuery interprets this as an error. - var xhr = new XMLHttpRequest(); - xhr.open('GET', window.location.href); - // If we don't set the mimetype, Firefox will complain. - xhr.overrideMimeType('text/plain'); - xhr.onreadystatechange = function() { - if (this.readyState === this.DONE) { + fetch(window.location.href) + .then(response => response.text()) + .then(responseText => { OptionsStore.get(function(options) { expect(options).to.have.property(testKeys[0]); - expect(options[testKeys[0]]).to.eql(xhr.responseText); + expect(options[testKeys[0]]).to.eql(responseText); done(); }); - } - }; - xhr.send(); + }); }); }); diff --git a/src/common/test/utils-test.js b/src/common/test/utils-test.js index 433810f3..27ef1048 100644 --- a/src/common/test/utils-test.js +++ b/src/common/test/utils-test.js @@ -276,12 +276,25 @@ describe('Utils', function() { Utils.getLocalFile('../images/icon16.png', 'base64', callback); }); + it('should work with getLocalURL', function(done) { + var KNOWN_PREFIX = ''; + var callback = function(data) { + expect(data.slice(0, KNOWN_PREFIX.length)).to.equal(KNOWN_PREFIX); + done(); + }; + + Utils.getLocalFile(Utils.getLocalURL('/common/options.html'), 'text', callback); + }); + + /* If we switch to promises rather than asynchronous callbacks, we can use these tests again. it('should supply an error arg to callback if file not found', function(done) { - Utils.getLocalFile('badfilename', 'text', function(val, err) { - expect(err).to.be.ok; - expect(val).to.not.be.ok; + try { + Utils.getLocalFile('badfilename', 'text', function(val, err) { + }); + } + catch (e) { done(); - }); + } }); it('should supply an error arg to callback if dataType is bad', function(done) { @@ -291,6 +304,7 @@ describe('Utils', function() { done(); }); }); + */ }); describe('getLocalURL', function() { diff --git a/src/common/utils.js b/src/common/utils.js index 1f3a9f6d..3afd3541 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -338,9 +338,8 @@ function getLocalURL(url) { // Makes an asynchrous XHR request for a local file (basically a thin wrapper). // `dataType` must be one of 'text', 'json', or 'base64'. -// `callback` will be called with the responseText as -// argument. -// If error occurs, `callback`'s second parameter will be an error. +// `callback` will be called with the response value, of a type depending on `dataType`. +// Errors are no expected for local files, and will result in an exception being thrown asynchrously. function getLocalFile(url, dataType, callback) { fetch(url) .then(response => { @@ -374,7 +373,7 @@ function getLocalFile(url, dataType, callback) { } }) .catch(err => { - callback(null, err); + throw new Error(`Error fetching local file: ${url}: ${err}`); }); } @@ -562,22 +561,11 @@ function getTopURL(win, justHostname) { // horribly slow rendering. For info see: // https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#Inactive_tabs // As an alternative, we can use a local XHR request/response. - +// This function just does a simple, local async request and then calls the callback. function asyncCallbackXHR(callback) { - var xhr = new window.XMLHttpRequest(); - xhr.open('HEAD', getLocalURL('/common/CHANGES.md')); - - xhr.onload = callback; - xhr.onerror = callback; - - try { - // On some platforms, xhr.send throws an error if the url is not found. - // On some platforms, it will call onerror and on some it won't. - xhr.send(); - } - catch(e) { - asyncCallbackTimeout(callback); - } + fetch(getLocalURL('/common/CHANGES.md'), {method: 'HEAD'}) + .then(callback) + .catch(callback); } function asyncCallbackTimeout(callback) { From 0b288c599437e5be0de2df4eb6cd0afbcd702344 Mon Sep 17 00:00:00 2001 From: Adam Pritchard Date: Tue, 1 Oct 2024 10:31:33 -0400 Subject: [PATCH 3/6] update instructions --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 70fe9595..2301dee2 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ *Markdown Here* is a Google Chrome, Firefox, Safari, Opera, and Thunderbird extension that lets you write email in Markdown and render them before sending. It also supports syntax highlighting (just specify the language in a fenced code block). -Writing email with code in it is pretty tedious. Writing Markdown with code in it is easy. I found myself writing email in Markdown in the Github in-browser editor, then copying the preview into email. This is a pretty absurd workflow, so I decided create a tool to write and render Markdown right in the email. +Writing email with code in it is pretty tedious. Writing Markdown with code in it is easy. I found myself writing email in Markdown in the GitHub in-browser editor, then copying the preview into email. This is a pretty absurd workflow, so I decided create a tool to write and render Markdown right in the email. To discover what can be done with Markdown in *Markdown Here*, check out the [Markdown Here Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Here-Cheatsheet) and the other [wiki pages](https://github.com/adam-p/markdown-here/wiki). @@ -62,7 +62,7 @@ After installing, make sure to restart Firefox/Thunderbird! #### Manual/Development 1. Clone this repo. -2. Follow the instructions in the MDN ["Setting up an extension development environment"](https://developer.mozilla.org/en/Setting_up_extension_development_environment) article. +2. Follow the instructions in the MDN ["Your first WebExtension"](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension#installing) article. ### Safari @@ -184,7 +184,7 @@ node build.js ``` -### Chrome and Opera extension +### Chrome, Opera, and Firefox (WebExtension) extension Create a file with a `.zip` extension containing these files and directories: @@ -192,9 +192,10 @@ Create a file with a `.zip` extension containing these files and directories: manifest.json common/ chrome/ +_locales ``` -### Firefox/Thunderbird extension +### Thunderbird (XUL) extension Create a file with a `.xpi` extension containing these files and directories: From 2ba02d9a169f2ed937b9d0199289ef3f7ddbe949 Mon Sep 17 00:00:00 2001 From: Adam Pritchard Date: Tue, 1 Oct 2024 12:46:47 -0400 Subject: [PATCH 4/6] update archiver packaged used for building The old version of archiver didn't seem to include CRCs. This would cause errors from 7zip and made me nervous about the builds being correct. --- src/common/test/utils-test.js | 1 + utils/package-lock.json | 1278 +++++++++++++++++++++++++-------- utils/package.json | 2 +- 3 files changed, 976 insertions(+), 305 deletions(-) diff --git a/src/common/test/utils-test.js b/src/common/test/utils-test.js index 27ef1048..5480497a 100644 --- a/src/common/test/utils-test.js +++ b/src/common/test/utils-test.js @@ -564,6 +564,7 @@ describe('Utils', function() { // I have found that Range.intersectsNode is broken on Chrome. I'm adding // test to see if/when it gets fixed. + // TODO: This test seems flawed. Why would test-elem-2 intersect the range that just contains test-elem-1? Hand-testing suggests that this is working as expected in Chrome and Firefox. Code that works around this probably-nonexistent bug should be reconsidered (especially since Postbox support is dropped). it('Range.intersectsNode is broken on Chrome', function() { var range = document.createRange(); range.selectNode($('#test-elem-1')[0]); diff --git a/utils/package-lock.json b/utils/package-lock.json index 88d40dfe..29f9497f 100644 --- a/utils/package-lock.json +++ b/utils/package-lock.json @@ -1,468 +1,1138 @@ { "name": "markdown-here-utils", "version": "0.0.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "archiver": { + "packages": { + "": { + "name": "markdown-here-utils", + "version": "0.0.0", + "dependencies": { + "archiver": "^7.0.1", + "file": "*", + "glob": "^7.1.3", + "markdown-it": "~3.0.5", + "metascript": "~1.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/abort-controller": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.0.0.tgz", - "integrity": "sha512-5QeR6Xc5hSA9X1rbQfcuQ6VZuUXOaEdB65Dhmk9duuRJHYif/ZyJfuyJqsQrj34PFjU5emv5/MmfgA8un06onw==", - "requires": { - "archiver-utils": "^2.0.0", - "async": "^2.0.0", - "buffer-crc32": "^0.2.1", - "glob": "^7.0.0", - "readable-stream": "^2.0.0", - "tar-stream": "^1.5.0", - "zip-stream": "^2.0.1" - } - }, - "archiver-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.0.0.tgz", - "integrity": "sha512-JRBgcVvDX4Mwu2RBF8bBaHcQCSxab7afsxAPYDQ5W+19quIPP5CfKE7Ql+UHs9wYvwsaNR8oDuhtf5iqrKmzww==", - "requires": { - "glob": "^7.0.0", - "graceful-fs": "^4.1.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", "lazystream": "^1.0.0", - "lodash.assign": "^4.2.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.toarray": "^4.4.0", - "lodash.union": "^4.6.0", + "lodash": "^4.17.15", "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, - "argparse": { + "node_modules/archiver-utils/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/argparse": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "requires": { + "dependencies": { "sprintf-js": "~1.0.2" } }, - "ascli": { + "node_modules/ascli": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/ascli/-/ascli-0.3.0.tgz", "integrity": "sha1-XmYjDlIZ/j6JUqTvtPIPrllqgTo=", - "requires": { - "colour": "^0.7.1", - "optjs": "^3.2.2" + "dependencies": { + "colour": "latest", + "optjs": "latest" } }, - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "requires": { - "lodash": "^4.17.10" - } + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" }, - "autolinker": { + "node_modules/autolinker": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.15.3.tgz", "integrity": "sha1-NCQX2PLzRhsUzwkIjV7fh5HcmDI=" }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "license": "Apache-2.0" }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, - "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } + "node_modules/bare-events": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", + "license": "Apache-2.0", + "optional": true }, - "brace-expansion": { + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { + "license": "MIT", + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" } }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, - "colour": { + "node_modules/colour": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", - "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=", + "engines": { + "node": ">=0.8" + } }, - "compress-commons": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", - "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", - "requires": { - "buffer-crc32": "^0.2.1", - "crc32-stream": "^2.0.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" } }, - "concat-map": { + "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, - "crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "requires": { - "buffer": "^5.1.0" + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" } }, - "crc32-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", - "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", - "requires": { - "crc": "^3.4.4", - "readable-stream": "^2.0.0" + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" } }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "requires": { - "once": "^1.4.0" + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" } }, - "file": { + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/file": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/file/-/file-0.2.2.tgz", "integrity": "sha1-w9/Y+M81Na5FXCtCPC5SY112tNM=" }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "fs.realpath": { + "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, - "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "requires": { - "readable-stream": "^2.0.5" + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } }, - "lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" }, - "lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } }, - "lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, - "lru-cache": { + "node_modules/lru-cache": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" }, - "markdown-it": { + "node_modules/markdown-it": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-3.0.7.tgz", "integrity": "sha1-GgCjLaFHK52hx5NeFdZD8NESWnA=", - "requires": { + "dependencies": { "argparse": "~ 1.0.0", "autolinker": "~ 0.15.2", "uc.micro": "~ 0.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" } }, - "metascript": { + "node_modules/metascript": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/metascript/-/metascript-1.0.0.tgz", "integrity": "sha1-k2oWnn/yq325+u6MdfvC58/As/U=", - "requires": { + "dependencies": { "ascli": "~0.3", "glob": "~3.2" }, + "bin": { + "metac": "bin/metac", + "metascript": "bin/metascript" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/metascript/node_modules/glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "deprecated": "Glob versions prior to v9 are no longer supported", "dependencies": { - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "requires": { - "inherits": "2", - "minimatch": "0.3" - } - }, - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - } + "inherits": "2", + "minimatch": "0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/metascript/node_modules/minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "engines": { + "node": "*" } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "normalize-path": { + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { + "dependencies": { "wrappy": "1" } }, - "optjs": { + "node_modules/optjs": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" }, - "path-is-absolute": { + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } }, - "sigmund": { + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" }, - "sprintf-js": { + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" + "node_modules/streamx": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", + "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" } }, - "tar-stream": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", - "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.1.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.0", - "xtend": "^4.0.0" + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" } }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/text-decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", + "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } }, - "uc.micro": { + "node_modules/uc.micro": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-0.1.0.tgz", "integrity": "sha1-7aESHR/blhVO1v3oJHu724MzCMo=" }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "wrappy": { + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "zip-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.0.1.tgz", - "integrity": "sha512-c+eUhhkDpaK87G/py74wvWLtz2kzMPNCCkUApkun50ssE0oQliIQzWpTnwjB+MTKVIf2tGzIgHyqW/Y+W77ecQ==", - "requires": { - "archiver-utils": "^2.0.0", - "compress-commons": "^1.2.0", - "readable-stream": "^2.0.0" + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" } } } diff --git a/utils/package.json b/utils/package.json index 9243d38a..87b3d019 100644 --- a/utils/package.json +++ b/utils/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "private": true, "dependencies": { - "archiver": "^3.0.0", + "archiver": "^7.0.1", "file": "*", "glob": "^7.1.3", "markdown-it": "~3.0.5", From e151d381d9dea8f92c5f5f822b94031ded606461 Mon Sep 17 00:00:00 2001 From: Adam Pritchard Date: Sat, 5 Oct 2024 16:45:37 -0400 Subject: [PATCH 5/6] add pointer cursor when hovering checkboxes and their labels --- src/common/options.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/options.html b/src/common/options.html index c6f091b8..0ceaeb00 100644 --- a/src/common/options.html +++ b/src/common/options.html @@ -282,6 +282,10 @@ display: none; } + input[type="checkbox"], input[type="checkbox"] + label { + cursor: pointer; + } + /* Custom PayPal button styles from http://visitsteve.com/made/diy-paypal-buttons/ */ .paypal-button { color: #2e3192; From d11c42a7cf6b24b38f728e570512b9f8d40e0015 Mon Sep 17 00:00:00 2001 From: Adam Pritchard Date: Sat, 12 Oct 2024 17:11:24 -0400 Subject: [PATCH 6/6] update version number and changelog --- src/chrome/backgroundscript.js | 3 +++ src/common/CHANGES.md | 9 ++++++++- src/manifest.json | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/chrome/backgroundscript.js b/src/chrome/backgroundscript.js index b077cbcd..d6b680ab 100644 --- a/src/chrome/backgroundscript.js +++ b/src/chrome/backgroundscript.js @@ -63,6 +63,9 @@ chrome.runtime.onInstalled.addListener((details) => { }); function upgradeCheck() { + // DISABLED FOR THIS RELEASE + return; + OptionsStore.get(function(options) { var appManifest = chrome.runtime.getManifest(); diff --git a/src/common/CHANGES.md b/src/common/CHANGES.md index fd711f3d..4b6d680a 100644 --- a/src/common/CHANGES.md +++ b/src/common/CHANGES.md @@ -1,10 +1,17 @@ Change Log ========== +2024-10-03: v2.14.0 +------------------- + +* Fixed [bug #722](https://github.com/adam-p/markdown-here/issues/722): Added support for WebExtensions manifest V3. (If you've seen warnings about the extension lately, this was why.) + - Thanks to [Andrew M. MacFie](https://github.com/amacfie) and [Alexander Popov](https://github.com/AlexWayfer). +* Fixed [bug #865](https://github.com/adam-p/markdown-here/issues/865): Add Chrome Store privacy information. + 2018-09-30: v2.13.4 -------------------- -* Fixed [bug #524] and [bug #526]: Due to v2.13.3 fix, Markdown Here didn't work in Thunderbird with a non-English UI. +* Fixed [bug #524](https://github.com/adam-p/markdown-here/issues/524) and [bug #526](https://github.com/adam-p/markdown-here/issues/526): Due to v2.13.3 fix, Markdown Here didn't work in Thunderbird with a non-English UI. - Thanks to [KSR-Yasuda](https://github.com/KSR-Yasuda), [ensleep](https://github.com/ensleep), [Pedro Silva](https://github.com/pmanu93), [Christophe Meyer](https://github.com/stombi), [littdky](https://github.com/littdky), [Michael Lashkevich](https://github.com/lashkevi), [morsedl](https://github.com/morsedl). diff --git a/src/manifest.json b/src/manifest.json index 2116dbc8..8b44ff6e 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "__MSG_app_name__", - "version": "2.13.4", + "version": "2.14.0", "description": "__MSG_app_slogan__", "homepage_url": "https://markdown-here.com", "default_locale": "en",