From 5d219e69d45e9e82c362519eb17d26122cb684c4 Mon Sep 17 00:00:00 2001 From: Denis Kolesnikov Date: Sun, 24 Feb 2019 21:54:34 +0300 Subject: [PATCH 1/2] Rewrited settings page using discovery --- core/settings.ejs | 19 +---- src/content/index.css | 24 ++++++ src/manifest.js | 2 +- src/settings.js | 165 +++++++++++++++++++++++++++++++++++++----- 4 files changed, 171 insertions(+), 39 deletions(-) diff --git a/core/settings.ejs b/core/settings.ejs index d3f02ae..a86ff90 100644 --- a/core/settings.ejs +++ b/core/settings.ejs @@ -3,25 +3,8 @@ <%= htmlWebpackPlugin.options.title %> - - -
-

Settings

-
-
- Expand level -
-
- - -
-
-
+
diff --git a/src/content/index.css b/src/content/index.css index 71d96fe..09543ff 100644 --- a/src/content/index.css +++ b/src/content/index.css @@ -5,3 +5,27 @@ .user-select { user-select: text; } + +.view-fieldset { + width: 400px; + display: flex; + margin: 8px 0; +} + +.view-fieldset > * + * { + margin-left: 6px; +} + +.view-fieldset .view-input { + flex: 1; +} + +.view-label { + line-height: 34px; +} + +.view-flash-message { + position: fixed; + top: 20px; + right: 20px; +} diff --git a/src/manifest.js b/src/manifest.js index a906ac2..286c2fc 100644 --- a/src/manifest.js +++ b/src/manifest.js @@ -11,7 +11,7 @@ module.exports = { ], options_ui: { // eslint-disable-line camelcase page: 'pages/settings.html', - chrome_style: true, // eslint-disable-line camelcase + chrome_style: false, // eslint-disable-line camelcase open_in_tab: false // eslint-disable-line camelcase }, content_scripts: [{ // eslint-disable-line camelcase diff --git a/src/settings.js b/src/settings.js index dff29b3..3d7d98b 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1,7 +1,85 @@ -const settingsForm = document.getElementById('settings-form'); -const expand = document.getElementById('expand'); -const save = document.getElementById('save'); -const status = document.getElementById('status'); +import { Widget } from '@discoveryjs/discovery/dist/lib.umd.js'; + +const discovery = new Widget(document.body); + +require('@discoveryjs/discovery/dist/lib.css'); +require('@discoveryjs/discovery/client/common.css'); +require('./content/index.css'); + +discovery.view.define('label', function(el, config = {}) { + const { text } = config; + + el.appendChild(document.createTextNode(String(text))); +}, { tag: 'label' }); + +discovery.view.define('fieldset', function(el, config, data, context) { + const { onChange, onInit } = config; + let { content } = config; + const { label } = content; + + if (!Array.isArray(content)) { + content = [content, { view: 'label', text: label }]; + } + + content.forEach(view => { + view.onInit = onInit; + view.onChange = onChange; + }); + + discovery.view.render(el, content, data, context); +}); + +discovery.view.define('flash-message', function(el, config) { + const { message } = config; + const { text, type } = message; + const view = 'alert' + (type ? `-${type}` : ''); + + discovery.view.render(el, { + view, + content: 'text:"' + text + '"' + }); +}); + +const modifiers = [ + { + view: 'input', + htmlType: 'number', + htmlMin: 0, + name: 'expandLevel', + label: 'Expand Level' + } +].map(content => ({ view: 'fieldset', content })); + +discovery.page.define('default', function(el, data) { + const { settings, message } = data; + + discovery.view.render(el, [ + 'h1:"Settings"', + { + view: 'context', + modifiers, + content: [ + { + view: 'button-primary', + content: 'text:"Save"', + onClick: (el, data, context) => { + saveSettings(context); + } + } + ] + }, + { + view: 'flash-message', + when: 'message', + message + } + ], { message }, settings); +}); + +const discoveryMeta = { + name: 'Settings', + createdAt: new Date().toISOString() // TODO fix in discovery +}; /** * Restores settings from storage @@ -10,25 +88,72 @@ function restoreSettings() { chrome.storage.sync.get({ expandLevel: 3 }, settings => { - expand.value = settings.expandLevel; + discovery.setData({ settings }, discoveryMeta); }); } -document.addEventListener('DOMContentLoaded', () => { - restoreSettings(); -}); +/** + * Saves settings to storage + * @param {Object} settings + */ +function saveSettings(settings) { + const { valid, errors } = validate(settings); -save.addEventListener('click', () => { - const expandLevel = expand.value; + if (valid) { + chrome.storage.sync.set(settings); - chrome.storage.sync.set({ - expandLevel - }, () => { - status.textContent = 'Options saved.'; - setTimeout(() => { - status.textContent = ''; - }, 750); - }); -}); + flashMessage({ settings }, 'Options saved.', 'success'); + } else { + flashMessage({ settings }, errors.join(' '), 'danger'); + } +} + +/** + * Creates flash info-message + * @param {Object} data + * @param {string} text + * @param {string} type + */ +function flashMessage(data, text, type) { + const message = { + text, + type + }; + + discovery.setData(Object.assign( + {}, + data, + { message } + )); + + setTimeout(() => { + discovery.setData(Object.assign( + {}, + data, + { message: null } + )); + }, 750); +} -settingsForm.addEventListener('submit', event => event.preventDefault()); +/** + * Validates settings + * @param {Object} settings + * @returns {Object} + */ +function validate(settings) { + const { expandLevel } = settings; + + let valid = true; + const errors = []; + + if (!expandLevel || !Number.isInteger(Number(expandLevel))) { + valid = false; + errors.push('Expand level must be an integer number!'); + } + + return { valid, errors }; +} + +document.addEventListener('DOMContentLoaded', () => { + restoreSettings(); +}); From 0186821413cbd09712d91a5be51313aedb854e56 Mon Sep 17 00:00:00 2001 From: Denis Kolesnikov Date: Sat, 9 Mar 2019 15:52:17 +0300 Subject: [PATCH 2/2] Fallback for CSP, check if HTML before parse --- CHANGELOG.md | 6 ++++ core/page.ejs | 2 +- package-lock.json | 65 ++++++++++++++++++++++++++++--------------- package.json | 2 +- src/content/index.js | 8 ++---- src/content/inject.js | 41 ++++++++++++++++----------- 6 files changed, 77 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d12439..531df45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.0 (09-03-2019) + +* Settings page is now using `discovery` under hood +* Some pages with CSP-header may brake extension functionality ([Crome bug](https://bugs.chromium.org/p/chromium/issues/detail?id=816121)). For such cases added fallback +* Extension now check if content is HTML before trying to parse JSON + ## 1.3.1 (13-02-2019) * Updated `discovery` and `jora` diff --git a/core/page.ejs b/core/page.ejs index 89dba33..fb6e6d4 100644 --- a/core/page.ejs +++ b/core/page.ejs @@ -2,7 +2,7 @@ - <%= htmlWebpackPlugin.options.title %> + <%= htmlWebpackPlugin.options.title %> diff --git a/package-lock.json b/package-lock.json index 919dd45..c8afba9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "jsondiscovery", - "version": "1.3.1", + "version": "1.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -194,7 +194,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -1971,7 +1971,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true }, @@ -2248,7 +2248,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true }, @@ -2623,7 +2623,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true }, @@ -5110,7 +5110,7 @@ "dependencies": { "convert-source-map": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", "dev": true }, @@ -6137,7 +6137,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -6479,7 +6479,7 @@ }, "source-map": { "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "optional": true, @@ -7238,7 +7238,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -7259,12 +7260,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7279,17 +7282,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -7406,7 +7412,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -7418,6 +7425,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7432,6 +7440,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7439,12 +7448,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -7463,6 +7474,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -7543,7 +7555,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -7555,6 +7568,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -7640,7 +7654,8 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -7676,6 +7691,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7695,6 +7711,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7738,12 +7755,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -8123,7 +8142,7 @@ }, "htmlescape": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", "dev": true }, @@ -9753,7 +9772,7 @@ "dependencies": { "colors": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/colors/-/colors-0.5.1.tgz", "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", "dev": true } @@ -12860,7 +12879,7 @@ }, "shasum": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", "dev": true, "requires": { @@ -13478,7 +13497,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } diff --git a/package.json b/package.json index dbf9863..f6fa240 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jsondiscovery", - "version": "1.3.1", + "version": "1.4.0", "description": "DiscoveryJson", "author": "exsdis@gmail.com", "license": "MIT", diff --git a/src/content/index.js b/src/content/index.js index 6d2c9b7..e4cdf84 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -105,6 +105,8 @@ function initDiscovery(settings) { }, '*'); }; + parent.postMessage({ scriptLoaded: true }, '*'); + return discovery; } @@ -128,9 +130,3 @@ window.addEventListener('message', function(event) { ); } }, false); - -// window.addEventListener('hashchange', () => { -// parent.postMessage({ -// hash: window.location.hash -// }, '*'); -// }); diff --git a/src/content/inject.js b/src/content/inject.js index 2be672f..5234748 100644 --- a/src/content/inject.js +++ b/src/content/inject.js @@ -13,9 +13,13 @@ function getSettings(cb) { let json; let raw; -try { - json = JSON.parse(document.body.innerText); -} catch (_) {} +const { innerText } = document.body; + +if (!innerText.startsWith('<')) { + try { + json = JSON.parse(innerText); + } catch (_) {} +} if (json) { const iframe = document.createElement('iframe'); @@ -27,21 +31,9 @@ if (json) { iframe.frameBorder = 0; raw = document.body.innerHTML; - document.body.innerHTML = ''; - - document.body.style.margin = 0; - document.body.style.padding = 0; - document.body.style.height = '100%'; - document.body.style.overflow = 'hidden'; - document.body.style.userSelect = 'none'; const wrapper = document.createElement('div'); - - wrapper.style.position = 'absolute'; - wrapper.style.top = 0; - wrapper.style.bottom = 0; - wrapper.style.left = 0; - wrapper.style.right = 0; + wrapper.isSet = false; document.body.appendChild(wrapper); wrapper.appendChild(iframe); @@ -74,6 +66,23 @@ if (json) { }; const onMessage = event => { + if (event.data && event.data.scriptLoaded && !wrapper.isSet) { + wrapper.style.position = 'absolute'; + wrapper.style.top = 0; + wrapper.style.bottom = 0; + wrapper.style.left = 0; + wrapper.style.right = 0; + wrapper.style['background-color'] = '#fff'; + + document.body.style.margin = 0; + document.body.style.padding = 0; + document.body.style.height = '100%'; + document.body.style.overflow = 'hidden'; + document.body.style.userSelect = 'none'; + + wrapper.isSet = true; + } + setHash(event.data.hash, event.data.replace); if (event.data && event.data.openSettings) {