diff --git a/web/app/common/constants.js b/web/app/common/constants.js
index 77937f25..5301d7ae 100644
--- a/web/app/common/constants.js
+++ b/web/app/common/constants.js
@@ -38,3 +38,29 @@ export const BLOCKING_DURATIONS = [
value: `${60 * 24}m`,
},
];
+
+/**
+ * Defines if browser storage features (cookies, localsrotage)
+ * are available or blocked via browser preferences
+ */
+export const IS_STORAGE_AVAILABLE = (() => {
+ try {
+ localStorage.setItem('localstorage_availability_test', null);
+ localStorage.removeItem('localstorage_availability_test');
+ } catch (e) {
+ return false;
+ }
+ return true;
+})();
+
+/**
+ * Defines whether iframe loaded in cross origin environment
+ * Usefull for checking if some privacy restriction may be applied
+ */
+export const IS_THIRD_PARTY = (() => {
+ try {
+ return window.parent.location.host !== window.location.host;
+ } catch (e) {
+ return true;
+ }
+})();
diff --git a/web/app/common/localStorage.js b/web/app/common/localStorage.js
new file mode 100644
index 00000000..00187297
--- /dev/null
+++ b/web/app/common/localStorage.js
@@ -0,0 +1,22 @@
+import { IS_STORAGE_AVAILABLE } from 'common/constants';
+
+const failMessage = 'remark42: localStorage access denied, check browser preferences';
+
+export const setItem = IS_STORAGE_AVAILABLE
+ ? localStorage.setItem.bind(localStorage)
+ : () => {
+ console.error(failMessage); // eslint-disable-line no-console
+ };
+
+export const getItem = IS_STORAGE_AVAILABLE
+ ? localStorage.getItem.bind(localStorage)
+ : () => {
+ console.error(failMessage); // eslint-disable-line no-console
+ return null;
+ };
+
+export const removeItem = IS_STORAGE_AVAILABLE
+ ? localStorage.removeItem.bind(localStorage)
+ : () => {
+ console.error(failMessage); // eslint-disable-line no-console
+ };
diff --git a/web/app/components/auth-panel/auth-panel.jsx b/web/app/components/auth-panel/auth-panel.jsx
index 2ed169dc..0926ddef 100644
--- a/web/app/components/auth-panel/auth-panel.jsx
+++ b/web/app/components/auth-panel/auth-panel.jsx
@@ -4,7 +4,7 @@ import { h, Component } from 'preact';
import UserId from './__user-id/auth-panel__user-id';
import Dropdown, { DropdownItem } from 'components/dropdown';
import Button from 'components/button';
-import { PROVIDER_NAMES } from 'common/constants';
+import { PROVIDER_NAMES, IS_STORAGE_AVAILABLE, IS_THIRD_PARTY } from 'common/constants';
import { requestDeletion } from 'utils/email';
import { getHandleClickProps } from 'common/accessibility';
@@ -76,28 +76,46 @@ export default class AuthPanel extends Component {
)}
- {!loggedIn && (
-
- Sign in to comment using{' '}
- {providers.map((provider, i) => {
- const comma = i === 0 ? '' : i === providers.length - 1 ? ' or ' : ', ';
+ {IS_STORAGE_AVAILABLE &&
+ !loggedIn && (
+
+ Sign in to comment using{' '}
+ {providers.map((provider, i) => {
+ const comma = i === 0 ? '' : i === providers.length - 1 ? ' or ' : ', ';
- return (
-
- {comma}
- props.onSignIn(provider))}
- role="link"
- >
- {PROVIDER_NAMES[provider]}
+ return (
+
+ {comma}
+ props.onSignIn(provider))}
+ role="link"
+ >
+ {PROVIDER_NAMES[provider]}
+
-
- );
- })}
- {'.'}
-
- )}
+ );
+ })}
+ {'.'}
+
+ )}
+
+ {!IS_STORAGE_AVAILABLE &&
+ IS_THIRD_PARTY && (
+
+ Disable third-party cookies blocking to sign in or open comments in{' '}
+
+ new page
+
+
+ )}
+
+ {!IS_STORAGE_AVAILABLE &&
+ !IS_THIRD_PARTY && Allow cookies to sign in and comment
}
{user.admin && (
diff --git a/web/app/components/thread/getCollapsedComments.js b/web/app/components/thread/getCollapsedComments.js
index 6568e6af..a239b0fa 100644
--- a/web/app/components/thread/getCollapsedComments.js
+++ b/web/app/components/thread/getCollapsedComments.js
@@ -1,5 +1,6 @@
import { LS_COLLAPSE_KEY } from 'common/constants';
+import { getItem as localStorageGetItem } from 'common/localStorage';
-const getCollapsedComments = () => JSON.parse(localStorage.getItem(LS_COLLAPSE_KEY) || '[]');
+const getCollapsedComments = () => JSON.parse(localStorageGetItem(LS_COLLAPSE_KEY) || '[]');
export default getCollapsedComments;
diff --git a/web/app/components/thread/saveCollapsedComments.js b/web/app/components/thread/saveCollapsedComments.js
index 3d0179c2..53b29b62 100644
--- a/web/app/components/thread/saveCollapsedComments.js
+++ b/web/app/components/thread/saveCollapsedComments.js
@@ -1,5 +1,6 @@
import { LS_COLLAPSE_KEY } from 'common/constants';
+import { setItem as localStorageSetItem } from 'common/localStorage';
-const saveCollapsedComments = comments => localStorage.setItem(LS_COLLAPSE_KEY, JSON.stringify(comments));
+const saveCollapsedComments = comments => localStorageSetItem(LS_COLLAPSE_KEY, JSON.stringify(comments));
export default saveCollapsedComments;
diff --git a/web/comments.ejs b/web/comments.ejs
new file mode 100644
index 00000000..40a8653c
--- /dev/null
+++ b/web/comments.ejs
@@ -0,0 +1,85 @@
+
+
+
+
+
+
Remark42 demo
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/webpack.config.js b/web/webpack.config.js
index 2b7efeed..869af3a1 100644
--- a/web/webpack.config.js
+++ b/web/webpack.config.js
@@ -114,6 +114,11 @@ module.exports = {
filename: 'last-comments.html',
inject: false,
}),
+ new Html({
+ template: path.resolve(__dirname, 'comments.ejs'),
+ filename: 'comments.html',
+ inject: false,
+ }),
new ExtractText({
filename: `remark.css`,
allChunks: true,