diff --git a/.vscode/settings.json b/.vscode/settings.json index 2cd5270f..3ae5ff72 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,7 @@ "editor.formatOnSave": true, "vetur.validation.template": false, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "eslint.validate": ["javascript", "vue", "typescript"] } diff --git a/README.md b/README.md index 57a56689..e322aaed 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ # Stylebot -![CI](https://github.com/ankit/stylebot/workflows/CI/badge.svg) +![Build](https://github.com/ankit/stylebot/actions/workflows/build.yml/badge.svg) [![Kofi](https://badgen.net/badge/icon/kofi?icon=kofi&label)](https://ko-fi.com/stylebot) [![Chrome Webstore Version](https://img.shields.io/chrome-web-store/v/oiaejidbmkiecgbjeifoejpgmdaleoha)](https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha) [![Chrome Users](https://badgen.net/chrome-web-store/users/oiaejidbmkiecgbjeifoejpgmdaleoha)](https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha) [![Webstore Rating](https://img.shields.io/chrome-web-store/stars/oiaejidbmkiecgbjeifoejpgmdaleoha)](https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha) -[![Follow on Twitter](https://badgen.net/twitter/follow/ahujaankit)](https://twitter.com/ahujaankit) ![License](https://img.shields.io/github/license/ankit/stylebot) Stylebot is a browser extension that lets you change the appearance of the web instantly. @@ -50,8 +49,7 @@ If you would like to add a new feature to Stylebot or f - Open `chrome://extensions` page. - Disable the official Stylebot version. - Enable the Developer mode. -- Click Load unpacked extension button -- Navigate to the project's `dist/` folder +- Load unpacked `dist/` as extension ### Google Drive Sync diff --git a/package.json b/package.json index 27de0991..3d8228dd 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@babel/core": "^7.10.1", "@babel/plugin-proposal-optional-chaining": "^7.10.1", "@babel/preset-env": "^7.10.1", - "@types/chrome": "^0.0.114", + "@types/chrome": "^0.0.193", "@types/dedent": "^0.7.0", "@types/jest": "^26.0.4", "@types/lodash": "^4.14.157", @@ -75,7 +75,6 @@ "bootstrap-vue": "^2.15.0", "copy-webpack-plugin": "^6.0.1", "cross-env": "^7.0.2", - "crx-hotreload": "^1.0.4", "css-loader": "^3.5.3", "cssnano": "^4.1.10", "date-fns": "^2.16.1", @@ -87,7 +86,6 @@ "eslint-plugin-prettier": "^3.1.4", "eslint-plugin-vue": "^6.2.2", "fibers": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^5.0.7", "hotkeys-js": "^3.8.1", "husky": "^4.2.5", "jest": "^26.1.0", diff --git a/src/background/cache.ts b/src/background/cache.ts deleted file mode 100644 index 6848e9c8..00000000 --- a/src/background/cache.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { defaultOptions } from '@stylebot/settings'; - -import BackgroundPageStyles from './styles'; -import BackgroundPageOptions from './options'; - -const init = async (): Promise<{ - styles: BackgroundPageStyles; - options: BackgroundPageOptions; -}> => { - return new Promise(resolve => { - chrome.storage.local.get(['options', 'styles'], items => { - let styles: BackgroundPageStyles; - - if (items['styles']) { - styles = new BackgroundPageStyles(items['styles']); - } else { - styles = new BackgroundPageStyles({}); - } - - let options: BackgroundPageOptions; - - if (items['options']) { - options = new BackgroundPageOptions(items['options']); - } else { - options = new BackgroundPageOptions(defaultOptions); - } - - resolve({ styles, options }); - }); - }); -}; - -export default { init }; diff --git a/src/background/contextmenu.ts b/src/background/contextmenu.ts index 414367eb..8ab0b318 100644 --- a/src/background/contextmenu.ts +++ b/src/background/contextmenu.ts @@ -4,54 +4,32 @@ import { OpenStylebotFromContextMenu } from '@stylebot/types'; import BackgroundPageUtils from './utils'; const CONTEXT_MENU_ID = 'stylebot-contextmenu'; - -const StyleElementContextMenu = () => { - chrome.contextMenus.create({ - contexts: ['all'], - title: t('style_element'), - parentId: CONTEXT_MENU_ID, - - onclick: (_info: chrome.contextMenus.OnClickData, tab: chrome.tabs.Tab) => { - if (tab.id) { - const message: OpenStylebotFromContextMenu = { - name: 'OpenStylebotFromContextMenu', - }; - - chrome.tabs.sendMessage(tab.id, message); - } - }, - }); -}; - -const ParentContextMenu = () => { - chrome.contextMenus.create({ - id: CONTEXT_MENU_ID, - title: 'Stylebot', - contexts: ['all'], - }); -}; - -const ViewOptionsContextMenu = () => { - chrome.contextMenus.create({ - contexts: ['all'], - title: t('view_options'), - parentId: CONTEXT_MENU_ID, - onclick: () => { - chrome.tabs.create({ - active: true, - url: 'options/index.html', - }); - }, - }); -}; +const VIEW_OPTIONS_MENU_ITEM_ID = 'view-options'; +const STYLE_ELEMENT_MENU_ITEM_ID = 'style-element'; const ContextMenu = { init(): void { this.remove(); - ParentContextMenu(); - StyleElementContextMenu(); - ViewOptionsContextMenu(); + chrome.contextMenus.create({ + id: CONTEXT_MENU_ID, + title: 'Stylebot', + contexts: ['all'], + }); + + chrome.contextMenus.create({ + contexts: ['all'], + title: t('style_element'), + parentId: CONTEXT_MENU_ID, + id: STYLE_ELEMENT_MENU_ITEM_ID, + }); + + chrome.contextMenus.create({ + contexts: ['all'], + title: t('view_options'), + parentId: CONTEXT_MENU_ID, + id: VIEW_OPTIONS_MENU_ITEM_ID, + }); }, update(tab: chrome.tabs.Tab): void { @@ -64,13 +42,15 @@ const ContextMenu = { chrome.contextMenus.update(CONTEXT_MENU_ID, { documentUrlPatterns: [''], }); - } else { - // If it isn't a valid url, hide the contextMenu - // Set the document pattern to foo/*random* - chrome.contextMenus.update(CONTEXT_MENU_ID, { - documentUrlPatterns: ['http://foo/' + Math.random()], - }); + + return; } + + // If it isn't a valid url, hide the contextMenu + // Set the document pattern to foo/*random* + chrome.contextMenus.update(CONTEXT_MENU_ID, { + documentUrlPatterns: ['http://foo/' + Math.random()], + }); }, remove(): void { @@ -78,4 +58,27 @@ const ContextMenu = { }, }; +chrome.contextMenus.onClicked.addListener((info, tab) => { + switch (info.menuItemId) { + case STYLE_ELEMENT_MENU_ITEM_ID: + if (tab?.id) { + const message: OpenStylebotFromContextMenu = { + name: 'OpenStylebotFromContextMenu', + }; + + chrome.tabs.sendMessage(tab.id, message); + } + + break; + + case VIEW_OPTIONS_MENU_ITEM_ID: + chrome.tabs.create({ + active: true, + url: 'options/index.html', + }); + + break; + } +}); + export default ContextMenu; diff --git a/src/background/index.ts b/src/background/index.ts index 742f156d..2cbba670 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -1,40 +1,19 @@ -import 'crx-hotreload'; +import './listeners'; -import Cache from './cache'; -import Listeners from './listeners'; import ContextMenu from './contextmenu'; import DefaultShortcutUpdate from './default-shortcut-update'; import StylesMetadataUpdate from './styles-metadata-update'; import StylesModifiedTimeUpdate from './styles-modified-time-update'; -import { setNotification } from '@stylebot/utils'; - (async () => { await DefaultShortcutUpdate(); await StylesMetadataUpdate(); await StylesModifiedTimeUpdate(); - - const { styles, options } = await Cache.init(); - - if (options.get('contextMenu')) { - ContextMenu.init(); - } - - Listeners.init(styles, options); - - chrome.browserAction.setBadgeBackgroundColor({ - color: '#555', - }); })(); -chrome.runtime.onInstalled.addListener(async ({ reason }) => { - if (reason === 'install') { - chrome.tabs.create({ - url: 'https://stylebot.dev/help' - }); - - setNotification('release/3.1', true); - } +chrome.runtime.setUninstallURL('https://stylebot.dev/goodbye'); +chrome.action.setBadgeBackgroundColor({ + color: '#555', }); -chrome.runtime.setUninstallURL('https://stylebot.dev/goodbye'); +ContextMenu.init(); diff --git a/src/background/listeners.ts b/src/background/listeners.ts index 7f7028a3..d8277389 100644 --- a/src/background/listeners.ts +++ b/src/background/listeners.ts @@ -1,5 +1,4 @@ import ContextMenu from './contextmenu'; -import BackgroundPageStyles from './styles'; import { GetCommands, @@ -24,126 +23,136 @@ import { RunGoogleDriveSync, } from './messages'; +import { get as getOption } from './options'; + import { TabUpdated, BackgroundPageMessage, BackgroundPageMessageResponse, } from '@stylebot/types'; -import BackgroundPageOptions from './options'; +import { setNotification } from '@stylebot/utils'; /** - * Initialize listeners for the background page + * Open Help page on installation */ -const init = ( - styles: BackgroundPageStyles, - options: BackgroundPageOptions -): void => { - chrome.runtime.onMessage.addListener( - ( - message: BackgroundPageMessage, - sender: chrome.runtime.MessageSender, - sendResponse: (response: BackgroundPageMessageResponse) => void - ) => { - switch (message.name) { - case 'GetCommands': - GetCommands(sendResponse); - break; - case 'SetCommands': - SetCommands(message); - break; - - case 'GetOption': - GetOption(message, options, sendResponse); - break; - case 'SetOption': - SetOption(message, options); - break; - case 'GetAllOptions': - GetAllOptions(options, sendResponse); - break; - case 'OpenOptionsPage': - OpenOptionsPage(); - break; - case 'OpenDonatePage': - OpenDonatePage(); - break; - - case 'SetStyle': - SetStyle(message, styles); - break; - case 'MoveStyle': - MoveStyle(message, styles); - break; - case 'GetAllStyles': - GetAllStyles(styles, sendResponse); - break; - case 'SetAllStyles': - SetAllStyles(message, styles); - break; - case 'GetStylesForPage': - GetStylesForPage(message, styles, sender, sendResponse); - break; - case 'GetStylesForIframe': - GetStylesForIframe(message, styles, sendResponse); - break; - case 'EnableStyle': - EnableStyle(message, styles); - break; - case 'DisableStyle': - DisableStyle(message, styles); - break; - - case 'SetReadability': - SetReadability(message, styles); - break; - case 'GetReadabilitySettings': - GetReadabilitySettings(sendResponse); - break; - case 'SetReadabilitySettings': - SetReadabilitySettings(message); - break; - - case 'GetImportCss': - GetImportCss(message, styles, sendResponse); - break; - case 'RunGoogleDriveSync': - RunGoogleDriveSync(message, styles, sendResponse); - break; - } - - return true; - } - ); - - /** - * Listen when an existing tab is updated - * and update the context-menu and browser-action - */ - chrome.tabs.onUpdated.addListener((tabId, _, tab) => { - if (tab.status === 'complete') { - if (options.get('contextMenu')) { - ContextMenu.update(tab); - } - } +chrome.runtime.onInstalled.addListener(async ({ reason }) => { + if (reason === 'install') { + chrome.tabs.create({ + url: 'https://stylebot.dev/help', + }); + + setNotification('release/3.1', true); + } +}); + +/** + * When an existing tab is updated, refresh the context-menu and action. + */ +chrome.tabs.onUpdated.addListener(async (tabId, _, tab) => { + const option = await getOption('contextMenu'); + + if (option && tab.status === 'complete') { + ContextMenu.update(tab); const message: TabUpdated = { name: 'TabUpdated', }; - chrome.tabs.sendMessage(tabId, message); - }); - - /** - * Listen when a tab is activated to update the context-menu - */ - chrome.tabs.onActivated.addListener(activeInfo => { - if (options.get('contextMenu')) { - chrome.tabs.get(activeInfo.tabId, tab => { - ContextMenu.update(tab); - }); + if (!tab.url?.includes('chrome-extension://')) { + chrome.tabs.sendMessage(tabId, message); + } + } +}); + +/** + * Listen when a tab is activated to refresh the context-menu. + */ +chrome.tabs.onActivated.addListener(async activeInfo => { + const option = await getOption('contextMenu'); + + if (option) { + chrome.tabs.get(activeInfo.tabId, tab => { + ContextMenu.update(tab); + }); + } +}); + +chrome.runtime.onMessage.addListener( + ( + message: BackgroundPageMessage, + sender: chrome.runtime.MessageSender, + sendResponse: (response: BackgroundPageMessageResponse) => void + ) => { + switch (message.name) { + case 'GetCommands': + GetCommands(sendResponse); + break; + case 'SetCommands': + SetCommands(message); + break; + + case 'GetOption': + GetOption(message, sendResponse); + break; + case 'SetOption': + SetOption(message); + break; + case 'GetAllOptions': + GetAllOptions(sendResponse); + break; + + case 'OpenOptionsPage': + OpenOptionsPage(); + break; + case 'OpenDonatePage': + OpenDonatePage(); + break; + + case 'SetStyle': + SetStyle(message); + break; + case 'MoveStyle': + MoveStyle(message); + break; + case 'GetAllStyles': + GetAllStyles(sendResponse); + break; + case 'SetAllStyles': + SetAllStyles(message); + break; + case 'GetStylesForPage': + GetStylesForPage(message, sender, sendResponse); + break; + case 'GetStylesForIframe': + GetStylesForIframe(message, sendResponse); + break; + case 'EnableStyle': + EnableStyle(message); + break; + case 'DisableStyle': + DisableStyle(message); + break; + + case 'SetReadability': + SetReadability(message); + break; + case 'GetReadabilitySettings': + GetReadabilitySettings(sendResponse); + break; + case 'SetReadabilitySettings': + SetReadabilitySettings(message); + break; + + case 'GetImportCss': + GetImportCss(message, sendResponse); + break; + + case 'RunGoogleDriveSync': + RunGoogleDriveSync(message, sendResponse); + break; } - }); -}; -export default { init }; + return true; + } +); diff --git a/src/background/messages.ts b/src/background/messages.ts index 75036d44..c118efc9 100644 --- a/src/background/messages.ts +++ b/src/background/messages.ts @@ -1,5 +1,22 @@ -import BackgroundPageStyles from './styles'; -import BackgroundPageOptions from './options'; +import { + set, + disable, + enable, + getAll, + setAll, + move, + getStylesForPage, + updateIcon, + setReadability, + getImportCss, + applyStylesToAllTabs, +} from './styles'; + +import { + get as getOption, + getAll as getAllOptions, + set as setOption, +} from './options'; import { GetOption as GetOptionType, @@ -34,87 +51,80 @@ import { import { get as getCommands, set as setCommands } from './commands'; -export const DisableStyle = ( - message: DisableStyleType, - styles: BackgroundPageStyles -): void => { - styles.disable(message.url); +export const DisableStyle = async ( + message: DisableStyleType +): Promise => { + await disable(message.url); + return applyStylesToAllTabs(); }; -export const EnableStyle = ( - message: EnableStyleType, - styles: BackgroundPageStyles -): void => { - styles.enable(message.url); +export const EnableStyle = async (message: EnableStyleType): Promise => { + await enable(message.url); + return applyStylesToAllTabs(); }; -export const SetStyle = ( - message: SetStyleType, - styles: BackgroundPageStyles -): void => { - styles.set(message.url, message.css, message.readability); -}; +export const SetStyle = (message: SetStyleType): Promise => + set(message.url, message.css, message.readability); -export const GetAllStyles = ( - styles: BackgroundPageStyles, +export const GetAllStyles = async ( sendResponse: (response: GetAllStylesResponse) => void -): void => { - sendResponse(styles.getAll()); +): Promise => { + const styles = await getAll(); + sendResponse(styles); }; -export const SetAllStyles = ( - message: SetAllStylesType, - styles: BackgroundPageStyles -): void => { - styles.setAll(message.styles, message.shouldPersist); +export const SetAllStyles = async ( + message: SetAllStylesType +): Promise => { + await setAll(message.styles); + return applyStylesToAllTabs(); }; -export const GetStylesForIframe = ( +export const GetStylesForIframe = async ( message: GetStylesForIframeType, - styles: BackgroundPageStyles, sendResponse: (response: GetStylesForPageResponse) => void -): void => { - sendResponse(styles.getStylesForPage(message.url, message.important)); +): Promise => { + const styles = await getAll(); + const pageStyles = getStylesForPage(message.url, styles, message.important); + + sendResponse(pageStyles); }; -export const GetStylesForPage = ( +export const GetStylesForPage = async ( message: GetStylesForPageType, - styles: BackgroundPageStyles, sender: chrome.runtime.MessageSender, sendResponse: (response: GetStylesForPageResponse) => void -): void => { +): Promise => { const tab = sender.tab || message.tab; if (!tab || !tab.url) { return; } - const response = styles.getStylesForPage(tab.url, message.important); - styles.updateIcon(tab, response.styles, response.defaultStyle); + const styles = await getAll(); + const response = getStylesForPage(tab.url, styles, message.important); + updateIcon(tab, response.styles, response.defaultStyle); sendResponse(response); }; -export const MoveStyle = ( - message: MoveStyleType, - styles: BackgroundPageStyles -): void => { - styles.move(message.sourceUrl, message.destinationUrl); +export const MoveStyle = (message: MoveStyleType): void => { + move(message.sourceUrl, message.destinationUrl); }; -export const GetOption = ( +export const GetOption = async ( message: GetOptionType, - options: BackgroundPageOptions, sendResponse: (response: GetOptionResponse) => void -): void => { - sendResponse(options.get(message.optionName)); +): Promise => { + const option = await getOption(message.optionName); + sendResponse(option); }; -export const GetAllOptions = ( - options: BackgroundPageOptions, +export const GetAllOptions = async ( sendResponse: (response: GetAllOptionsResponse) => void -): void => { - sendResponse(options.getAll()); +): Promise => { + const options = await getAllOptions(); + sendResponse(options); }; export const OpenOptionsPage = (): void => { @@ -125,11 +135,8 @@ export const OpenDonatePage = (): void => { chrome.tabs.create({ url: 'https://ko-fi.com/stylebot' }); }; -export const SetOption = ( - message: SetOptionType, - options: BackgroundPageOptions -): void => { - options.set(message.option.name, message.option.value); +export const SetOption = (message: SetOptionType): void => { + setOption(message.option.name, message.option.value); }; export const GetCommands = async ( @@ -143,11 +150,8 @@ export const SetCommands = (message: SetCommandsType): void => { setCommands(message.value); }; -export const SetReadability = ( - message: SetReadabilityType, - styles: BackgroundPageStyles -): void => { - styles.setReadability(message.url, message.value); +export const SetReadability = (message: SetReadabilityType): void => { + setReadability(message.url, message.value); }; export const GetReadabilitySettings = async ( @@ -165,18 +169,17 @@ export const SetReadabilitySettings = ( export const GetImportCss = async ( message: GetImportCssType, - styles: BackgroundPageStyles, + sendResponse: (response: GetImportCssResponse) => void ): Promise => { - const css = await styles.getImportCss(message.url); + const css = await getImportCss(message.url); sendResponse(css); }; export const RunGoogleDriveSync = async ( _message: RunGoogleDriveSyncType, - styles: BackgroundPageStyles, sendResponse: (response: RunGoogleDriveSyncResponse) => void ): Promise => { - await runGoogleDriveSync(styles); + await runGoogleDriveSync(); sendResponse(); }; diff --git a/src/background/options.ts b/src/background/options.ts index 5ba603f8..46e086ff 100644 --- a/src/background/options.ts +++ b/src/background/options.ts @@ -1,41 +1,34 @@ -import ContextMenu from './contextmenu'; import { StylebotOptions } from '@stylebot/types'; +import { defaultOptions } from '@stylebot/settings'; -class BackgroundPageOptions { - options: StylebotOptions; - - constructor(options: StylebotOptions) { - this.options = options; - } - - get(name: keyof StylebotOptions): StylebotOptions[keyof StylebotOptions] { - return this.options[name]; - } - - getAll(): StylebotOptions { - return this.options; - } - - set( - name: keyof StylebotOptions, - value: StylebotOptions[keyof StylebotOptions] - ): void { - this.options = { - ...this.options, - [name]: value, - }; - - chrome.storage.local.set({ options: this.options }); - - // If the option was contextMenu, update it - if (name === 'contextMenu') { - if (value === false) { - ContextMenu.remove(); +export const getAll = (): Promise => + new Promise(resolve => { + chrome.storage.local.get('options', items => { + if (items['options']) { + resolve(items['options']); } else { - ContextMenu.init(); + resolve(defaultOptions); } - } - } -} - -export default BackgroundPageOptions; + }); + }); + +export const get = async ( + name: keyof StylebotOptions +): Promise => { + const options = await getAll(); + return options[name]; +}; + +export const set = async ( + name: keyof StylebotOptions, + value: StylebotOptions[keyof StylebotOptions] +): Promise => { + let options = await getAll(); + + options = { + ...options, + [name]: value, + }; + + chrome.storage.local.set({ options }); +}; diff --git a/src/background/styles.ts b/src/background/styles.ts index c515fb53..734eaf32 100644 --- a/src/background/styles.ts +++ b/src/background/styles.ts @@ -2,6 +2,7 @@ import * as postcss from 'postcss'; import { getCurrentTimestamp } from '@stylebot/utils'; import { appendImportantToDeclarations } from '@stylebot/css'; + import { Style, StyleMap, @@ -11,211 +12,208 @@ import { import BackgroundPageUtils from './utils'; -class BackgroundPageStyles { - styles: StyleMap; - - constructor(styles: StyleMap) { - this.styles = styles; - } - - persistStorage(): void { - chrome.storage.local.set({ - styles: this.styles, - - 'styles-metadata': { - modifiedTime: getCurrentTimestamp(), - }, +export const updateIcon = ( + tab: chrome.tabs.Tab, + styles: Array \ No newline at end of file + diff --git a/src/readability/reader.ts b/src/readability/reader.ts index 7f86e891..59acf976 100644 --- a/src/readability/reader.ts +++ b/src/readability/reader.ts @@ -10,7 +10,7 @@ import { ReadabilityArticle } from '@stylebot/types'; import { cacheDocument } from './cache'; const initCss = async (root: ShadowRoot): Promise => { - const cssUrl = chrome.extension.getURL('readability/index.css'); + const cssUrl = chrome.runtime.getURL('readability/index.css'); return new Promise(resolve => { fetch(cssUrl, { method: 'GET' }) diff --git a/src/sync/google-drive/sync.ts b/src/sync/google-drive/sync.ts index f6e53280..9c0f68cf 100644 --- a/src/sync/google-drive/sync.ts +++ b/src/sync/google-drive/sync.ts @@ -15,7 +15,10 @@ import { downloadSyncFile, writeSyncFile, } from './sync-file'; -import BackgroundPageStyles from 'background/styles'; +import { + setAll as setAllStyles, + getAll as getAllStyles, +} from '../../background/styles'; const getStylesBlob = (styles: StyleMap) => new Blob([JSON.stringify(styles)], { type: 'application/json' }); @@ -43,10 +46,9 @@ const writeToRemote = async ( */ const writeToLocal = async ( syncMetadata: GoogleDriveSyncMetadata, - styles: StyleMap, - backgroundPageStyles: BackgroundPageStyles + styles: StyleMap ) => { - backgroundPageStyles.setAll(styles, false); + await setAllStyles(styles); return setGoogleDriveSyncMetadata({ ...syncMetadata, @@ -59,14 +61,13 @@ const writeToLocal = async ( */ const merge = async ( accessToken: string, - syncMetadata: GoogleDriveSyncMetadata, - backgroundPageStyles: BackgroundPageStyles + syncMetadata: GoogleDriveSyncMetadata ) => { - const localStyles = backgroundPageStyles.getAll(); + const localStyles = await getAllStyles(); const remoteStyles = await downloadSyncFile(accessToken, syncMetadata.id); const mergedStyles = mergeStyles(localStyles, remoteStyles); - await writeToLocal(syncMetadata, mergedStyles, backgroundPageStyles); + await writeToLocal(syncMetadata, mergedStyles); await writeToRemote(accessToken, syncMetadata, mergedStyles); }; @@ -79,9 +80,8 @@ const merge = async ( * - Else, write remote styles to local * 4) If local styles' modified timestamp > remote sync timestamp, write local styles to remote. */ -export const runGoogleDriveSync = async ( - backgroundPageStyles: BackgroundPageStyles -): Promise => { +export const runGoogleDriveSync = async (): Promise => { + const styles = await getAllStyles(); const accessToken = await getAccessToken(); const remoteSyncMetadata = await getSyncFileMetadata(accessToken); @@ -90,7 +90,7 @@ export const runGoogleDriveSync = async ( if (!remoteSyncMetadata) { console.debug('did not find remote sync file, updating remote...'); - const blob = getStylesBlob(backgroundPageStyles.getAll()); + const blob = getStylesBlob(styles); const remoteSyncMetadata = await writeSyncFile(accessToken, blob); return setGoogleDriveSyncMetadata(remoteSyncMetadata); } @@ -99,7 +99,7 @@ export const runGoogleDriveSync = async ( if (!localSyncMetadata) { console.debug('no local sync metadata found. merging local and remote...'); - return merge(accessToken, remoteSyncMetadata, backgroundPageStyles); + return merge(accessToken, remoteSyncMetadata); } const localStylesMetadata = await getLocalStylesMetadata(); @@ -122,7 +122,7 @@ export const runGoogleDriveSync = async ( 'both local and remote were updated since last sync, merging local and remote...' ); - return merge(accessToken, remoteSyncMetadata, backgroundPageStyles); + return merge(accessToken, remoteSyncMetadata); } console.debug('remote was updated since last sync, updating local...'); @@ -131,17 +131,13 @@ export const runGoogleDriveSync = async ( remoteSyncMetadata.id ); - return writeToLocal(remoteSyncMetadata, remoteStyles, backgroundPageStyles); + return writeToLocal(remoteSyncMetadata, remoteStyles); } // check if local styles were modified v/s remote if (compareAsc(localStylesModifiedTime, remoteSyncTime) > 0) { console.debug('local was updated since last sync, updating remote...'); - return writeToRemote( - accessToken, - remoteSyncMetadata, - backgroundPageStyles.getAll() - ); + return writeToRemote(accessToken, remoteSyncMetadata, styles); } return setGoogleDriveSyncMetadata({ diff --git a/webpack.config.js b/webpack.config.js index 707882a9..839c2511 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,7 +8,6 @@ const { VueLoaderPlugin } = require('vue-loader'); const CopyPlugin = require('copy-webpack-plugin'); const ExtensionReloader = require('webpack-extension-reloader'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const ProgressBarPlugin = require('progress-bar-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); @@ -21,6 +20,7 @@ const config = { stats: 'errors-only', mode: process.env.NODE_ENV, context: `${__dirname}/src`, + devtool: 'inline-source-map', optimization: { minimize: process.env.NODE_ENV === 'production', @@ -37,17 +37,6 @@ const config = { ], }, - entry: { - 'sync/index': './sync/index.ts', - 'popup/index': './popup/index.ts', - 'editor/index': './editor/index.ts', - 'options/index': './options/index.ts', - 'background/index': './background/index.ts', - 'inject-css/index': './inject-css/index.ts', - 'monaco-editor/iframe/index': './monaco-editor/iframe/index.ts', - 'readability/index': './readability/index.ts', - }, - output: { publicPath: '/', filename: '[name].js', @@ -126,18 +115,7 @@ const config = { plugins: [ new ProgressBarPlugin(), - new webpack.DefinePlugin({ - global: 'window', - }), new VueLoaderPlugin(), - new ForkTsCheckerWebpackPlugin({ - typescript: { - configFile: '../tsconfig.json', - extensions: { - vue: true, - }, - }, - }), new MiniCssExtractPlugin({ filename: '[name].css', }), @@ -223,8 +201,9 @@ const config = { let jsonContent = JSON.parse(content); if (config.mode === 'development') { - jsonContent['content_security_policy'] = - "script-src 'self' 'unsafe-eval'; object-src 'self'"; + jsonContent['content_security_policy'] = { + extension_page: "script-src 'self'; object-src 'self'", + }; } if (process.env.BROWSER === 'firefox') { @@ -268,4 +247,29 @@ function transformHtml(content) { }); } -module.exports = config; +const backgroundPageConfig = { + ...config, + entry: { + 'background/index': './background/index.ts', + }, + plugins: [ + new webpack.DefinePlugin({ + global: 'this', + }), + ], +}; + +const clientConfig = { + ...config, + entry: { + 'sync/index': './sync/index.ts', + 'popup/index': './popup/index.ts', + 'editor/index': './editor/index.ts', + 'options/index': './options/index.ts', + 'inject-css/index': './inject-css/index.ts', + 'monaco-editor/iframe/index': './monaco-editor/iframe/index.ts', + 'readability/index': './readability/index.ts', + }, +}; + +module.exports = [backgroundPageConfig, clientConfig]; diff --git a/yarn.lock b/yarn.lock index 1d720331..91506aa4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.8.3": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== @@ -1165,11 +1165,6 @@ dependencies: defer-to-connect "^1.0.1" -"@types/anymatch@*": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" - integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== - "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.9" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" @@ -1203,10 +1198,10 @@ dependencies: "@babel/types" "^7.3.0" -"@types/chrome@^0.0.114": - version "0.0.114" - resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.114.tgz#8ceb33fa261f4b9e307fa7344ba8182d8d410d4e" - integrity sha512-i7qRr74IrxHtbnrZSKUuP5Uvd5EOKwlwJq/yp7+yTPihOXnPhNQO4Z5bqb1XTnrjdbUKEJicaVVbhcgtRijmLA== +"@types/chrome@^0.0.193": + version "0.0.193" + resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.193.tgz#cd0dc5033f27a243d228aebe566c3ec19ef17e36" + integrity sha512-R8C84oqvk8A8C8G1viBd8qLpDr86Y/jwD+KLgzUekbIT9RGds6a9GnlQyg8P7ltnGogTMHkiEQK0ZlcrvTeo3Q== dependencies: "@types/filesystem" "*" "@types/har-format" "*" @@ -1319,9 +1314,9 @@ integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== "@types/source-list-map@*": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" - integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== + version "0.1.6" + resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.6.tgz#164e169dd061795b50b83c19e4d3be09f8d3a454" + integrity sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g== "@types/stack-utils@^1.0.1": version "1.0.1" @@ -1338,10 +1333,10 @@ resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== -"@types/tapable@*": - version "1.0.6" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74" - integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA== +"@types/tapable@^1": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.12.tgz#bc2cab12e87978eee89fb21576b670350d6d86ab" + integrity sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q== "@types/tinycolor2@^1.4.2": version "1.4.2" @@ -1349,40 +1344,40 @@ integrity sha512-PeHg/AtdW6aaIO2a+98Xj7rWY4KC1E6yOy7AFknJQ7VXUGNrMlyxDFxJo7HqLtjQms/ZhhQX52mLVW/EX3JGOw== "@types/uglify-js@*": - version "3.9.3" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.3.tgz#d94ed608e295bc5424c9600e6b8565407b6b4b6b" - integrity sha512-KswB5C7Kwduwjj04Ykz+AjvPcfgv/37Za24O2EDzYNbwyzOo8+ydtvzUfZ5UMguiVu29Gx44l1A6VsPPcmYu9w== + version "3.17.5" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.17.5.tgz#905ce03a3cbbf2e31cbefcbc68d15497ee2e17df" + integrity sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ== dependencies: source-map "^0.6.1" "@types/webpack-sources@*": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-1.4.0.tgz#e58f1f05f87d39a5c64cf85705bdbdbb94d4d57e" - integrity sha512-c88dKrpSle9BtTqR6ifdaxu1Lvjsl3C5OsfvuUbUwdXymshv1TkufUAXBajCCUM/f/TmnkZC/Esb03MinzSiXQ== + version "3.2.3" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-3.2.3.tgz#b667bd13e9fa15a9c26603dce502c7985418c3d8" + integrity sha512-4nZOdMwSPHZ4pTEZzSp0AsTM4K7Qmu40UKW4tJDiOVs20UzYF9l+qUe4s0ftfN0pin06n+5cWWDJXH+sbhAiDw== dependencies: "@types/node" "*" "@types/source-list-map" "*" source-map "^0.7.3" "@types/webpack-sources@^0.1.5": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.8.tgz#078d75410435993ec8a0a2855e88706f3f751f81" - integrity sha512-JHB2/xZlXOjzjBB6fMOpH1eQAfsrpqVVIbneE0Rok16WXwFaznaI5vfg75U5WgGJm7V9W1c4xeRQDjX/zwvghA== + version "0.1.12" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.12.tgz#9beb82c5dc5483c0fb947da1723f4044b07f6204" + integrity sha512-+vRVqE3LzMLLVPgZHUeI8k1YmvgEky+MOir5fQhKvFxpB8uZ0CFnGqxkRAmf8jvNhUBQzhuGZpIMNWZDeEyDIA== dependencies: "@types/node" "*" "@types/source-list-map" "*" source-map "^0.6.1" "@types/webpack@^4.39.8": - version "4.41.21" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.21.tgz#cc685b332c33f153bb2f5fc1fa3ac8adeb592dee" - integrity sha512-2j9WVnNrr/8PLAB5csW44xzQSJwS26aOnICsP3pSGCEdsu6KYtfQ6QJsVUKHWRnm1bL7HziJsfh5fHqth87yKA== + version "4.41.38" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.38.tgz#5a40ac81bdd052bf405e8bdcf3e1236f6db6dc26" + integrity sha512-oOW7E931XJU1mVfCnxCVgv8GLFL768pDO5u2Gzk82i8yTIgX6i7cntyZOkZYb/JtYM8252SN9bQp9tgkVDSsRw== dependencies: - "@types/anymatch" "*" "@types/node" "*" - "@types/tapable" "*" + "@types/tapable" "^1" "@types/uglify-js" "*" "@types/webpack-sources" "*" + anymatch "^3.0.0" source-map "^0.6.0" "@types/yargs-parser@*": @@ -1903,6 +1898,14 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +anymatch@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + anymatch@^3.0.3, anymatch@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" @@ -3383,11 +3386,6 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -crx-hotreload@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/crx-hotreload/-/crx-hotreload-1.0.4.tgz#227b1a8aa2ddfc5c29075ad2ee3e3bc37f7a239b" - integrity sha512-3mJMMbjoLhHmhNubyIPKmgLvr9V6UZ/yKaZW1WKb2n7yHs1R10VVCAUgQ00amR6fTmM/aiEvZHx+jzhSSf0CGA== - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -4857,22 +4855,6 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -fork-ts-checker-webpack-plugin@^5.0.7: - version "5.0.7" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.0.7.tgz#a462bd863bbd654bad14a25518006ab99b7b13a0" - integrity sha512-X7zHKTx4is5YSKa9bDiXGzv8v5K3bsUrZlZgr3F8DeCVsb3oik/+0Mo+K138Sdjh4mpzoHcuUgsrIgZeLIXovw== - dependencies: - "@babel/code-frame" "^7.8.3" - chalk "^2.4.1" - cosmiconfig "^6.0.0" - deepmerge "^4.2.2" - fs-extra "^9.0.0" - memfs "^3.1.2" - minimatch "^3.0.4" - schema-utils "1.0.0" - semver "^5.6.0" - tapable "^1.0.0" - form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -4902,7 +4884,7 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-extra@9.0.1, fs-extra@^9.0.0: +fs-extra@9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== @@ -4937,11 +4919,6 @@ fs-minipass@^2.0.0: dependencies: minipass "^3.0.0" -fs-monkey@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.1.tgz#4a82f36944365e619f4454d9fff106553067b781" - integrity sha512-fcSa+wyTqZa46iWweI7/ZiUfegOZl0SG8+dltIwFXo7+zYU9J9kpS3NB6pZcSlJdhvIwp81Adx2XhZorncxiaA== - fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -7064,13 +7041,6 @@ mem@^5.0.0: mimic-fn "^2.1.0" p-is-promise "^2.1.0" -memfs@^3.1.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.2.0.tgz#f9438e622b5acd1daa8a4ae160c496fdd1325b26" - integrity sha512-f/xxz2TpdKv6uDn6GtHee8ivFyxwxmPuXatBb1FBwxYNuVpbM3k/Y1Z+vC0mH/dIXXrukYfe3qe5J32Dfjg93A== - dependencies: - fs-monkey "1.0.1" - memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" @@ -9191,7 +9161,7 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -schema-utils@1.0.0, schema-utils@^1.0.0: +schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== @@ -10923,11 +10893,16 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" -ws@7.3.1, ws@^7.2.0, ws@^7.2.3: +ws@7.3.1, ws@^7.2.3: version "7.3.1" resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== +ws@^7.2.0: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"