mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 09:42:07 +08:00
DEV: Drop unsupported-browser plugin (#10261)
Discourse 2.6 will not have support for older browsers (e.g. IE11)
This commit is contained in:
parent
fab8b8649e
commit
85d1677b26
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -54,7 +54,6 @@ bootsnap-compile-cache/
|
||||||
!/plugins/discourse-narrative-bot
|
!/plugins/discourse-narrative-bot
|
||||||
!/plugins/discourse-presence
|
!/plugins/discourse-presence
|
||||||
!/plugins/discourse-local-dates
|
!/plugins/discourse-local-dates
|
||||||
!/plugins/discourse-unsupported-browser
|
|
||||||
/plugins/*/auto_generated/
|
/plugins/*/auto_generated/
|
||||||
|
|
||||||
/spec/fixtures/plugins/my_plugin/auto_generated
|
/spec/fixtures/plugins/my_plugin/auto_generated
|
||||||
|
|
|
@ -97,7 +97,7 @@ export default Component.extend({
|
||||||
// on Desktop, shows the button at the beginning of the selection
|
// on Desktop, shows the button at the beginning of the selection
|
||||||
// on Mobile, shows the button at the end of the selection
|
// on Mobile, shows the button at the end of the selection
|
||||||
const isMobileDevice = this.site.isMobileDevice;
|
const isMobileDevice = this.site.isMobileDevice;
|
||||||
const { isIOS, isAndroid, isSafari, isOpera, isIE11 } = this.capabilities;
|
const { isIOS, isAndroid, isSafari, isOpera } = this.capabilities;
|
||||||
const showAtEnd = isMobileDevice || isIOS || isAndroid || isOpera;
|
const showAtEnd = isMobileDevice || isIOS || isAndroid || isOpera;
|
||||||
|
|
||||||
// Don't mess with the original range as it results in weird behaviours
|
// Don't mess with the original range as it results in weird behaviours
|
||||||
|
@ -125,10 +125,7 @@ export default Component.extend({
|
||||||
const parent = markerElement.parentNode;
|
const parent = markerElement.parentNode;
|
||||||
parent.removeChild(markerElement);
|
parent.removeChild(markerElement);
|
||||||
// merge back all text nodes so they don't get messed up
|
// merge back all text nodes so they don't get messed up
|
||||||
if (!isIE11) {
|
parent.normalize();
|
||||||
// Skip this fix in IE11 - .normalize causes the selection to change
|
|
||||||
parent.normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// work around Safari that would sometimes lose the selection
|
// work around Safari that would sometimes lose the selection
|
||||||
if (isSafari) {
|
if (isSafari) {
|
||||||
|
|
|
@ -113,8 +113,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
const siteSettings = container.lookup("site-settings:main");
|
const siteSettings = container.lookup("site-settings:main");
|
||||||
const { isIE11 } = container.lookup("capabilities:main");
|
if (!siteSettings.show_copy_button_on_codeblocks) {
|
||||||
if (!siteSettings.show_copy_button_on_codeblocks || isIE11) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ export default {
|
||||||
return p.toString() === "[object SafariRemoteNotification]";
|
return p.toString() === "[object SafariRemoteNotification]";
|
||||||
})(!window["safari"] || safari.pushNotification);
|
})(!window["safari"] || safari.pushNotification);
|
||||||
caps.isChrome = !!window.chrome && !caps.isOpera;
|
caps.isChrome = !!window.chrome && !caps.isOpera;
|
||||||
caps.isIE11 = !!ua.match(/Trident.*rv\:11\./);
|
|
||||||
|
|
||||||
caps.canPasteImages = caps.isChrome || caps.isFirefox;
|
caps.canPasteImages = caps.isChrome || caps.isFirefox;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
|
||||||
// Any IE only polyfill should be moved in discourse-unsupported-browser plugin
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags#Polyfill
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags#Polyfill
|
||||||
// IE and EDGE
|
// IE and EDGE
|
||||||
if (RegExp.prototype.flags === undefined) {
|
if (RegExp.prototype.flags === undefined) {
|
||||||
|
|
|
@ -75,7 +75,6 @@ class Plugin::Metadata
|
||||||
"docker_manager",
|
"docker_manager",
|
||||||
"lazy-yt",
|
"lazy-yt",
|
||||||
"poll",
|
"poll",
|
||||||
"discourse-unsupported-browser",
|
|
||||||
"discourse-fontawesome-pro",
|
"discourse-fontawesome-pro",
|
||||||
"discourse-staff-alias",
|
"discourse-staff-alias",
|
||||||
])
|
])
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import I18n from "I18n";
|
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
|
||||||
|
|
||||||
function initializeInternetExplorerDeprecation(api) {
|
|
||||||
const siteSettings = api.container.lookup("site-settings:main");
|
|
||||||
if (siteSettings.browser_deprecation_warning) {
|
|
||||||
const { isIE11 } = api.container.lookup("capabilities:main");
|
|
||||||
if (isIE11) {
|
|
||||||
api.addGlobalNotice(
|
|
||||||
I18n.t("discourse_unsupported_browser.deprecation_warning"),
|
|
||||||
"browser-deprecation-warning",
|
|
||||||
{ dismissable: true, dismissDuration: moment.duration(1, "week") }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "discourse-unsupported-browser",
|
|
||||||
|
|
||||||
initialize() {
|
|
||||||
withPluginApi("0.8.37", initializeInternetExplorerDeprecation);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,444 +0,0 @@
|
||||||
@media screen and (max-width: 767px) {
|
|
||||||
table.staff-logs tr {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 1fr 1fr 1fr 0.5fr;
|
|
||||||
-ms-grid-rows: auto auto;
|
|
||||||
td {
|
|
||||||
display: -ms-grid;
|
|
||||||
&.staff-users {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
-ms-grid-column-span: 2;
|
|
||||||
}
|
|
||||||
&.created-at {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 4;
|
|
||||||
}
|
|
||||||
&.action {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&.subject {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
-ms-grid-column-span: 3;
|
|
||||||
}
|
|
||||||
&.details {
|
|
||||||
-ms-grid-row: 3;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
-ms-grid-column-span: 3;
|
|
||||||
}
|
|
||||||
&.context {
|
|
||||||
-ms-grid-row: 4;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
-ms-grid-column-span: 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// desktop/login.scss
|
|
||||||
.d-modal.create-account {
|
|
||||||
.login-form {
|
|
||||||
form,
|
|
||||||
table {
|
|
||||||
display: block; //IE11
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/admin/dashboard.scss
|
|
||||||
.dashboard,
|
|
||||||
.dashboard-next {
|
|
||||||
.charts {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
|
||||||
-ms-grid-rows: 1fr 1fr;
|
|
||||||
.admin-report {
|
|
||||||
-ms-grid-column-span: 4;
|
|
||||||
|
|
||||||
&:nth-of-type(1) {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&:nth-of-type(2) {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&:nth-of-type(3) {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 5;
|
|
||||||
}
|
|
||||||
&:nth-of-type(4) {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 9;
|
|
||||||
}
|
|
||||||
&:nth-of-type(5) {
|
|
||||||
-ms-grid-row: 3;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&:nth-of-type(6) {
|
|
||||||
-ms-grid-row: 3;
|
|
||||||
-ms-grid-column: 5;
|
|
||||||
}
|
|
||||||
&:nth-of-type(7) {
|
|
||||||
-ms-grid-row: 3;
|
|
||||||
-ms-grid-column: 9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-report {
|
|
||||||
&.consolidated-page-views {
|
|
||||||
-ms-grid-column-span: 12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.counters-list {
|
|
||||||
.counters-header {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 2fr 1fr 1fr 1fr 1fr;
|
|
||||||
.counters-cell {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column-span: 1;
|
|
||||||
&:nth-of-type(1) {
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&:nth-of-type(2) {
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
}
|
|
||||||
&:nth-of-type(3) {
|
|
||||||
-ms-grid-column: 3;
|
|
||||||
}
|
|
||||||
&:nth-of-type(4) {
|
|
||||||
-ms-grid-column: 4;
|
|
||||||
}
|
|
||||||
&:nth-of-type(5) {
|
|
||||||
-ms-grid-column: 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/admin/api.scss
|
|
||||||
table.web-hooks.grid {
|
|
||||||
@media screen and (max-width: 767px) {
|
|
||||||
tr {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 0.5fr 1fr 1fr 0.5fr;
|
|
||||||
td {
|
|
||||||
display: -ms-grid;
|
|
||||||
&.delivery-status {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&.payload-url {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
}
|
|
||||||
&.description {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 3;
|
|
||||||
}
|
|
||||||
&.controls {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.api-keys {
|
|
||||||
@media screen and (max-width: 767px) {
|
|
||||||
tr {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 0.25fr 1fr 1fr;
|
|
||||||
-ms-grid-rows: auto auto;
|
|
||||||
td {
|
|
||||||
display: -ms-grid;
|
|
||||||
|
|
||||||
&.key {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
-ms-grid-column-span: 3;
|
|
||||||
}
|
|
||||||
&.key-user {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&.key-controls {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
-ms-grid-column-span: 2;
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 125px 125px;
|
|
||||||
button:first-of-type {
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
button:last-of-type {
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/admin/staff_logs.scss
|
|
||||||
table.search-logs-list {
|
|
||||||
@media screen and (max-width: 767px) {
|
|
||||||
tr {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 1fr 1fr 1fr;
|
|
||||||
-ms-grid-rows: auto 2em;
|
|
||||||
td {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-rows: auto auto;
|
|
||||||
.label {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
}
|
|
||||||
&.term {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
-ms-grid-column-span: 3;
|
|
||||||
}
|
|
||||||
&.col:nth-of-type(2) {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&.col:nth-of-type(3) {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
}
|
|
||||||
&.col:nth-of-type(4) {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/admin/admin_report_counters.scss
|
|
||||||
.admin-report {
|
|
||||||
.admin-report-counters {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 2fr 1fr 1fr 1fr 1fr;
|
|
||||||
.cell {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column-span: 1;
|
|
||||||
|
|
||||||
&:nth-of-type(1) {
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&:nth-of-type(2) {
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
}
|
|
||||||
&:nth-of-type(3) {
|
|
||||||
-ms-grid-column: 3;
|
|
||||||
}
|
|
||||||
&:nth-of-type(4) {
|
|
||||||
-ms-grid-column: 4;
|
|
||||||
}
|
|
||||||
&:nth-of-type(5) {
|
|
||||||
-ms-grid-column: 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/admin/users.scss
|
|
||||||
.admin-users-list {
|
|
||||||
@media screen and (max-width: 767px) {
|
|
||||||
tr.user {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 1fr 1fr 1fr;
|
|
||||||
-ms-grid-rows: 2em 1fr 3em 3em;
|
|
||||||
td {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 1fr;
|
|
||||||
-ms-grid-rows: 1fr 1fr;
|
|
||||||
.label {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
div:not(.label) {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
&.username {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
-ms-grid-column-span: 2;
|
|
||||||
}
|
|
||||||
&.user-status {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 3;
|
|
||||||
}
|
|
||||||
&.email {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
-ms-grid-column-span: 3;
|
|
||||||
}
|
|
||||||
&.last-emailed {
|
|
||||||
-ms-grid-row: 3;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&.last-seen {
|
|
||||||
-ms-grid-row: 3;
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
}
|
|
||||||
&.topics-entered {
|
|
||||||
-ms-grid-row: 3;
|
|
||||||
-ms-grid-column: 3;
|
|
||||||
}
|
|
||||||
&.posts-read {
|
|
||||||
-ms-grid-row: 4;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
&.time-read {
|
|
||||||
-ms-grid-row: 4;
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
}
|
|
||||||
&.created {
|
|
||||||
-ms-grid-row: 4;
|
|
||||||
-ms-grid-column: 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/base/groups.scss
|
|
||||||
.groups-boxes {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.group-box {
|
|
||||||
flex: 1 1 24%;
|
|
||||||
margin: 1%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/base/_topic-list.scss
|
|
||||||
.list-controls {
|
|
||||||
.combo-box .combo-box-header {
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.topic-list {
|
|
||||||
.link-bottom-line {
|
|
||||||
.discourse-tags {
|
|
||||||
-ms-flex: 1 0 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/base/user.scss
|
|
||||||
.user-content-wrapper {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 1fr 5fr;
|
|
||||||
-ms-grid-rows: auto auto 1fr auto;
|
|
||||||
.user-primary-navigation {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
-ms-grid-column-span: 2;
|
|
||||||
}
|
|
||||||
.user-secondary-navigation {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
.solo-preference,
|
|
||||||
.user-content,
|
|
||||||
.spinner {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
-ms-grid-column-span: 2;
|
|
||||||
}
|
|
||||||
.user-secondary-navigation + .user-content {
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
-ms-grid-column-span: 1;
|
|
||||||
}
|
|
||||||
.user-additional-controls {
|
|
||||||
-ms-grid-row: 3;
|
|
||||||
-ms-grid-column-align: start;
|
|
||||||
-ms-grid-row-align: start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.avatar-selector {
|
|
||||||
.avatar-choice {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 2em 1fr auto;
|
|
||||||
-ms-grid-rows: auto auto;
|
|
||||||
input[type="radio"] {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 1;
|
|
||||||
}
|
|
||||||
label.radio {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 2;
|
|
||||||
}
|
|
||||||
span.avatar-uploader {
|
|
||||||
-ms-grid-row: 1;
|
|
||||||
-ms-grid-column: 3;
|
|
||||||
}
|
|
||||||
.error {
|
|
||||||
-ms-grid-row: 2;
|
|
||||||
-ms-grid-column-span: 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/base/topic-post.scss
|
|
||||||
aside.quote {
|
|
||||||
.title {
|
|
||||||
padding: 12px 12px 1px 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/base/menu-panel.scss
|
|
||||||
div.menu-links-header {
|
|
||||||
.menu-links-row {
|
|
||||||
li {
|
|
||||||
&.glyphs {
|
|
||||||
max-width: 65%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/base/header.scss
|
|
||||||
.extra-info-wrapper {
|
|
||||||
flex: 1 1 0%;
|
|
||||||
|
|
||||||
.topic-header-extra {
|
|
||||||
flex: 1 0 0%;
|
|
||||||
min-width: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/select-kit/dropdown-select-box.scss
|
|
||||||
.select-kit {
|
|
||||||
&.dropdown-select-box {
|
|
||||||
.select-kit-row {
|
|
||||||
.texts {
|
|
||||||
width: 0;
|
|
||||||
|
|
||||||
.desc {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// common/select-kit/category-row.scss
|
|
||||||
.select-kit {
|
|
||||||
.category-row {
|
|
||||||
.category-desc {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
en:
|
|
||||||
js:
|
|
||||||
discourse_unsupported_browser:
|
|
||||||
deprecation_warning: This site will soon remove support for Internet Explorer 11 - please update your browser
|
|
|
@ -1,4 +0,0 @@
|
||||||
en:
|
|
||||||
site_settings:
|
|
||||||
discourse_unsupported_browser_enabled: "Enable temporary support for old browsers. This plugin is an effort to maintain compatibility with older browsers and will be completely removed in the near future."
|
|
||||||
browser_deprecation_warning: "Show a warning to deprecated browsers"
|
|
|
@ -1,7 +0,0 @@
|
||||||
plugins:
|
|
||||||
discourse_unsupported_browser_enabled:
|
|
||||||
default: false
|
|
||||||
hidden: true
|
|
||||||
browser_deprecation_warning:
|
|
||||||
default: true
|
|
||||||
client: true
|
|
|
@ -1,52 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# name: discourse-unsupported-browser
|
|
||||||
# about: Attempts to provide support for old and unsupported browser through polyfills
|
|
||||||
# version: 1.0
|
|
||||||
# authors: Joffrey Jaffeux, David Taylor, Daniel Waterworth, Robin Ward
|
|
||||||
# url: https://github.com/discourse/discourse/tree/master/plugins/discourse-unsupported-browser
|
|
||||||
|
|
||||||
enabled_site_setting :discourse_unsupported_browser_enabled
|
|
||||||
hide_plugin if self.respond_to?(:hide_plugin)
|
|
||||||
|
|
||||||
register_asset 'stylesheets/ie.scss'
|
|
||||||
|
|
||||||
# We can't use register asset for an optional resource. Instead copy it after plugins have
|
|
||||||
# been activated so it can be uploaded to CDNs.
|
|
||||||
DiscourseEvent.on(:after_plugin_activation) do ||
|
|
||||||
polyfill_path = "#{Plugin::Instance.js_path}/#{self.directory_name}-optional.js"
|
|
||||||
FileUtils.cp("#{Rails.root}/public/plugins/discourse-unsupported-browser/js/ie.js", polyfill_path)
|
|
||||||
Rails.configuration.assets.precompile << "plugins/discourse-unsupported-browser-optional.js"
|
|
||||||
end
|
|
||||||
|
|
||||||
after_initialize do
|
|
||||||
# Conditionally load the stylesheet
|
|
||||||
register_asset_filter do |type, request|
|
|
||||||
request.nil? || request.env['HTTP_USER_AGENT'] =~ /MSIE|Trident/
|
|
||||||
end
|
|
||||||
|
|
||||||
register_anonymous_cache_key(:ie) do
|
|
||||||
unless defined?(@is_ie)
|
|
||||||
session = @env[self.class::RACK_SESSION]
|
|
||||||
# don't initialize params until later
|
|
||||||
# otherwise you get a broken params on the request
|
|
||||||
params = {}
|
|
||||||
|
|
||||||
@is_ie = BrowserDetection.browser(@env[self.class::USER_AGENT]) == :ie
|
|
||||||
end
|
|
||||||
|
|
||||||
@is_ie
|
|
||||||
end
|
|
||||||
|
|
||||||
# not using patch on preload_script as js is fine and we need this file
|
|
||||||
# to be loaded before other files
|
|
||||||
register_html_builder('server:before-script-load') do |controller|
|
|
||||||
if BrowserDetection.browser(controller.request.env['HTTP_USER_AGENT']) == :ie
|
|
||||||
path = controller.helpers.script_asset_path('plugins/discourse-unsupported-browser-optional')
|
|
||||||
|
|
||||||
<<~JAVASCRIPT
|
|
||||||
<script src="#{path}"></script>
|
|
||||||
JAVASCRIPT
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,984 +0,0 @@
|
||||||
/* eslint-disable */
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
|
|
||||||
if (!Object.entries) {
|
|
||||||
Object.entries = function(obj) {
|
|
||||||
var ownProps = Object.keys(obj),
|
|
||||||
i = ownProps.length,
|
|
||||||
resArray = new Array(i); // preallocate the Array
|
|
||||||
while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]];
|
|
||||||
|
|
||||||
return resArray;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
|
|
||||||
// missing in ie only
|
|
||||||
if (!Object.values) {
|
|
||||||
Object.values = function(obj) {
|
|
||||||
var ownProps = Object.keys(obj),
|
|
||||||
i = ownProps.length,
|
|
||||||
resArray = new Array(i); // preallocate the Array
|
|
||||||
while (i--) resArray[i] = obj[ownProps[i]];
|
|
||||||
|
|
||||||
return resArray;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/fr/docs/Web/API/NodeList/forEach
|
|
||||||
if (window.NodeList && !NodeList.prototype.forEach) {
|
|
||||||
NodeList.prototype.forEach = function(callback, thisArg) {
|
|
||||||
thisArg = thisArg || window;
|
|
||||||
for (var i = 0; i < this.length; i++) {
|
|
||||||
callback.call(thisArg, this[i], i, this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill
|
|
||||||
if (!Array.prototype.includes) {
|
|
||||||
Object.defineProperty(Array.prototype, "includes", {
|
|
||||||
value: function(searchElement, fromIndex) {
|
|
||||||
if (this == null) {
|
|
||||||
throw new TypeError('"this" is null or not defined');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Let O be ? ToObject(this value).
|
|
||||||
var o = Object(this);
|
|
||||||
|
|
||||||
// 2. Let len be ? ToLength(? Get(O, "length")).
|
|
||||||
var len = o.length >>> 0;
|
|
||||||
|
|
||||||
// 3. If len is 0, return false.
|
|
||||||
if (len === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Let n be ? ToInteger(fromIndex).
|
|
||||||
// (If fromIndex is undefined, this step produces the value 0.)
|
|
||||||
var n = fromIndex | 0;
|
|
||||||
|
|
||||||
// 5. If n ≥ 0, then
|
|
||||||
// a. Let k be n.
|
|
||||||
// 6. Else n < 0,
|
|
||||||
// a. Let k be len + n.
|
|
||||||
// b. If k < 0, let k be 0.
|
|
||||||
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
|
|
||||||
|
|
||||||
function sameValueZero(x, y) {
|
|
||||||
return (
|
|
||||||
x === y ||
|
|
||||||
(typeof x === "number" &&
|
|
||||||
typeof y === "number" &&
|
|
||||||
isNaN(x) &&
|
|
||||||
isNaN(y))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. Repeat, while k < len
|
|
||||||
while (k < len) {
|
|
||||||
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
|
|
||||||
// b. If SameValueZero(searchElement, elementK) is true, return true.
|
|
||||||
if (sameValueZero(o[k], searchElement)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// c. Increase k by 1.
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. Return false
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes#Polyfill
|
|
||||||
if (!String.prototype.includes) {
|
|
||||||
Object.defineProperty(String.prototype, "includes", {
|
|
||||||
value: function(search, start) {
|
|
||||||
if (typeof start !== "number") {
|
|
||||||
start = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start + search.length > this.length) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return this.indexOf(search, start) !== -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
|
|
||||||
if (!Array.prototype.find) {
|
|
||||||
Object.defineProperty(Array.prototype, "find", {
|
|
||||||
value: function(predicate) {
|
|
||||||
// 1. Let O be ? ToObject(this value).
|
|
||||||
if (this == null) {
|
|
||||||
throw new TypeError('"this" is null or not defined');
|
|
||||||
}
|
|
||||||
|
|
||||||
var o = Object(this);
|
|
||||||
|
|
||||||
// 2. Let len be ? ToLength(? Get(O, "length")).
|
|
||||||
var len = o.length >>> 0;
|
|
||||||
|
|
||||||
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
|
|
||||||
if (typeof predicate !== "function") {
|
|
||||||
throw new TypeError("predicate must be a function");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
||||||
var thisArg = arguments[1];
|
|
||||||
|
|
||||||
// 5. Let k be 0.
|
|
||||||
var k = 0;
|
|
||||||
|
|
||||||
// 6. Repeat, while k < len
|
|
||||||
while (k < len) {
|
|
||||||
// a. Let Pk be ! ToString(k).
|
|
||||||
// b. Let kValue be ? Get(O, Pk).
|
|
||||||
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
|
|
||||||
// d. If testResult is true, return kValue.
|
|
||||||
var kValue = o[k];
|
|
||||||
if (predicate.call(thisArg, kValue, k, o)) {
|
|
||||||
return kValue;
|
|
||||||
}
|
|
||||||
// e. Increase k by 1.
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. Return undefined.
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
configurable: true,
|
|
||||||
writable: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
|
|
||||||
// Production steps of ECMA-262, Edition 6, 22.1.2.1
|
|
||||||
if (!Array.from) {
|
|
||||||
Array.from = (function() {
|
|
||||||
var toStr = Object.prototype.toString;
|
|
||||||
var isCallable = function(fn) {
|
|
||||||
return typeof fn === "function" || toStr.call(fn) === "[object Function]";
|
|
||||||
};
|
|
||||||
var toInteger = function(value) {
|
|
||||||
var number = Number(value);
|
|
||||||
if (isNaN(number)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (number === 0 || !isFinite(number)) {
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
|
|
||||||
};
|
|
||||||
var maxSafeInteger = Math.pow(2, 53) - 1;
|
|
||||||
var toLength = function(value) {
|
|
||||||
var len = toInteger(value);
|
|
||||||
return Math.min(Math.max(len, 0), maxSafeInteger);
|
|
||||||
};
|
|
||||||
|
|
||||||
// The length property of the from method is 1.
|
|
||||||
return function from(arrayLike /*, mapFn, thisArg */) {
|
|
||||||
// 1. Let C be the this value.
|
|
||||||
var C = this;
|
|
||||||
|
|
||||||
// 2. Let items be ToObject(arrayLike).
|
|
||||||
var items = Object(arrayLike);
|
|
||||||
|
|
||||||
// 3. ReturnIfAbrupt(items).
|
|
||||||
if (arrayLike == null) {
|
|
||||||
throw new TypeError(
|
|
||||||
"Array.from requires an array-like object - not null or undefined"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. If mapfn is undefined, then let mapping be false.
|
|
||||||
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
|
|
||||||
var T;
|
|
||||||
if (typeof mapFn !== "undefined") {
|
|
||||||
// 5. else
|
|
||||||
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
|
|
||||||
if (!isCallable(mapFn)) {
|
|
||||||
throw new TypeError(
|
|
||||||
"Array.from: when provided, the second argument must be a function"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
||||||
if (arguments.length > 2) {
|
|
||||||
T = arguments[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 10. Let lenValue be Get(items, "length").
|
|
||||||
// 11. Let len be ToLength(lenValue).
|
|
||||||
var len = toLength(items.length);
|
|
||||||
|
|
||||||
// 13. If IsConstructor(C) is true, then
|
|
||||||
// 13. a. Let A be the result of calling the [[Construct]] internal method
|
|
||||||
// of C with an argument list containing the single item len.
|
|
||||||
// 14. a. Else, Let A be ArrayCreate(len).
|
|
||||||
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
|
|
||||||
|
|
||||||
// 16. Let k be 0.
|
|
||||||
var k = 0;
|
|
||||||
// 17. Repeat, while k < len… (also steps a - h)
|
|
||||||
var kValue;
|
|
||||||
while (k < len) {
|
|
||||||
kValue = items[k];
|
|
||||||
if (mapFn) {
|
|
||||||
A[k] =
|
|
||||||
typeof T === "undefined"
|
|
||||||
? mapFn(kValue, k)
|
|
||||||
: mapFn.call(T, kValue, k);
|
|
||||||
} else {
|
|
||||||
A[k] = kValue;
|
|
||||||
}
|
|
||||||
k += 1;
|
|
||||||
}
|
|
||||||
// 18. Let putStatus be Put(A, "length", len, true).
|
|
||||||
A.length = len;
|
|
||||||
// 20. Return A.
|
|
||||||
return A;
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
|
|
||||||
if (typeof Object.assign !== "function") {
|
|
||||||
// Must be writable: true, enumerable: false, configurable: true
|
|
||||||
Object.defineProperty(Object, "assign", {
|
|
||||||
value: function assign(target) {
|
|
||||||
// .length of function is 2
|
|
||||||
"use strict";
|
|
||||||
if (target == null) {
|
|
||||||
// TypeError if undefined or null
|
|
||||||
throw new TypeError("Cannot convert undefined or null to object");
|
|
||||||
}
|
|
||||||
|
|
||||||
var to = Object(target);
|
|
||||||
|
|
||||||
for (var index = 1; index < arguments.length; index++) {
|
|
||||||
var nextSource = arguments[index];
|
|
||||||
|
|
||||||
if (nextSource != null) {
|
|
||||||
// Skip over if undefined or null
|
|
||||||
for (var nextKey in nextSource) {
|
|
||||||
// Avoid bugs when hasOwnProperty is shadowed
|
|
||||||
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
|
||||||
to[nextKey] = nextSource[nextKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return to;
|
|
||||||
},
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat#Polyfill
|
|
||||||
if (!String.prototype.repeat) {
|
|
||||||
String.prototype.repeat = function(count) {
|
|
||||||
"use strict";
|
|
||||||
if (this == null)
|
|
||||||
throw new TypeError("can't convert " + this + " to object");
|
|
||||||
|
|
||||||
var str = "" + this;
|
|
||||||
// To convert string to integer.
|
|
||||||
count = +count;
|
|
||||||
// Check NaN
|
|
||||||
if (count != count) count = 0;
|
|
||||||
|
|
||||||
if (count < 0) throw new RangeError("repeat count must be non-negative");
|
|
||||||
|
|
||||||
if (count == Infinity)
|
|
||||||
throw new RangeError("repeat count must be less than infinity");
|
|
||||||
|
|
||||||
count = Math.floor(count);
|
|
||||||
if (str.length == 0 || count == 0) return "";
|
|
||||||
|
|
||||||
// Ensuring count is a 31-bit integer allows us to heavily optimize the
|
|
||||||
// main part. But anyway, most current (August 2014) browsers can't handle
|
|
||||||
// strings 1 << 28 chars or longer, so:
|
|
||||||
if (str.length * count >= 1 << 28)
|
|
||||||
throw new RangeError(
|
|
||||||
"repeat count must not overflow maximum string size"
|
|
||||||
);
|
|
||||||
|
|
||||||
var maxCount = str.length * count;
|
|
||||||
count = Math.floor(Math.log(count) / Math.log(2));
|
|
||||||
while (count) {
|
|
||||||
str += str;
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
str += str.substring(0, maxCount - str.length);
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill
|
|
||||||
if (!String.prototype.startsWith) {
|
|
||||||
Object.defineProperty(String.prototype, "startsWith", {
|
|
||||||
value: function(search, rawPos) {
|
|
||||||
var pos = rawPos > 0 ? rawPos | 0 : 0;
|
|
||||||
return this.substring(pos, pos + search.length) === search;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Symbol-ES6 v0.1.2
|
|
||||||
* ES6 Symbol polyfill in pure ES5.
|
|
||||||
*
|
|
||||||
* @license Copyright (c) 2017-2018 Rousan Ali, MIT License
|
|
||||||
*
|
|
||||||
* Codebase: https://github.com/rousan/symbol-es6
|
|
||||||
* Date: 28th Jan, 2018
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(global, factory) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
if (typeof module === "object" && typeof module.exports === "object") {
|
|
||||||
// For the environment like NodeJS, CommonJS etc where module or
|
|
||||||
// module.exports objects are available
|
|
||||||
module.exports = factory(global);
|
|
||||||
} else {
|
|
||||||
// For browser context, where global object is window
|
|
||||||
factory(global);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* window is for browser environment and global is for NodeJS environment */
|
|
||||||
})(typeof window !== "undefined" ? window : global, function(global) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var defineProperty = Object.defineProperty;
|
|
||||||
|
|
||||||
var defineProperties = Object.defineProperties;
|
|
||||||
|
|
||||||
var symbolHiddenCounter = 0;
|
|
||||||
|
|
||||||
var globalSymbolRegistry = [];
|
|
||||||
|
|
||||||
var slice = Array.prototype.slice;
|
|
||||||
|
|
||||||
var ES6 = typeof global.ES6 === "object" ? global.ES6 : (global.ES6 = {});
|
|
||||||
|
|
||||||
var isArray = Array.isArray;
|
|
||||||
|
|
||||||
var objectToString = Object.prototype.toString;
|
|
||||||
|
|
||||||
var push = Array.prototype.push;
|
|
||||||
|
|
||||||
var emptyFunction = function() {};
|
|
||||||
|
|
||||||
var simpleFunction = function(arg) {
|
|
||||||
return arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
var isCallable = function(fn) {
|
|
||||||
return typeof fn === "function";
|
|
||||||
};
|
|
||||||
|
|
||||||
var isConstructor = function(fn) {
|
|
||||||
return isCallable(fn);
|
|
||||||
};
|
|
||||||
|
|
||||||
var Iterator = function() {};
|
|
||||||
|
|
||||||
var ArrayIterator = function ArrayIterator(array, flag) {
|
|
||||||
this._array = array;
|
|
||||||
this._flag = flag;
|
|
||||||
this._nextIndex = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
var StringIterator = function StringIterator(string, flag) {
|
|
||||||
this._string = string;
|
|
||||||
this._flag = flag;
|
|
||||||
this._nextIndex = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
var isES6Running = function() {
|
|
||||||
return false; /* Now 'false' for testing purpose */
|
|
||||||
};
|
|
||||||
|
|
||||||
var isObject = function(value) {
|
|
||||||
return (
|
|
||||||
value !== null &&
|
|
||||||
(typeof value === "object" || typeof value === "function")
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6FunctionPrototypeHasInstanceSymbol = function(instance) {
|
|
||||||
if (typeof this !== "function") return false;
|
|
||||||
return instance instanceof this;
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6InstanceOfOperator = function(object, constructor) {
|
|
||||||
if (!isObject(constructor))
|
|
||||||
throw new TypeError("Right-hand side of 'instanceof' is not an object");
|
|
||||||
|
|
||||||
var hasInstanceSymbolProp = constructor[Symbol.hasInstance];
|
|
||||||
if (typeof hasInstanceSymbolProp === "undefined") {
|
|
||||||
return object instanceof constructor;
|
|
||||||
} else if (typeof hasInstanceSymbolProp !== "function") {
|
|
||||||
throw new TypeError(typeof hasInstanceSymbolProp + " is not a function");
|
|
||||||
} else {
|
|
||||||
return hasInstanceSymbolProp.call(constructor, object);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generates name for a symbol instance and this name will be used as
|
|
||||||
// property key for property symbols internally.
|
|
||||||
var generateSymbolName = function(id) {
|
|
||||||
return "@@_____" + id + "_____";
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generates id for next Symbol instance
|
|
||||||
var getNextSymbolId = function() {
|
|
||||||
return symbolHiddenCounter++;
|
|
||||||
};
|
|
||||||
|
|
||||||
var setupSymbolInternals = function(symbol, desc) {
|
|
||||||
defineProperties(symbol, {
|
|
||||||
_description: {
|
|
||||||
value: desc
|
|
||||||
},
|
|
||||||
_isSymbol: {
|
|
||||||
value: true
|
|
||||||
},
|
|
||||||
_id: {
|
|
||||||
value: getNextSymbolId()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return symbol;
|
|
||||||
};
|
|
||||||
|
|
||||||
var checkSymbolInternals = function(symbol) {
|
|
||||||
return (
|
|
||||||
symbol._isSymbol === true &&
|
|
||||||
typeof symbol._id === "number" &&
|
|
||||||
typeof symbol._description === "string"
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
var isSymbol = function(symbol) {
|
|
||||||
return symbol instanceof Symbol && checkSymbolInternals(symbol);
|
|
||||||
};
|
|
||||||
|
|
||||||
var symbolFor = function(key) {
|
|
||||||
key = String(key);
|
|
||||||
var registryLength = globalSymbolRegistry.length,
|
|
||||||
record,
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
for (; i < registryLength; ++i) {
|
|
||||||
record = globalSymbolRegistry[i];
|
|
||||||
if (record.key === key) return record.symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
record = {
|
|
||||||
key: key,
|
|
||||||
symbol: Symbol(key)
|
|
||||||
};
|
|
||||||
globalSymbolRegistry.push(record);
|
|
||||||
return record.symbol;
|
|
||||||
};
|
|
||||||
|
|
||||||
var symbolKeyFor = function(symbol) {
|
|
||||||
if (!ES6.isSymbol(symbol))
|
|
||||||
throw new TypeError(String(symbol) + " is not a symbol");
|
|
||||||
var registryLength = globalSymbolRegistry.length,
|
|
||||||
record,
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
for (; i < registryLength; ++i) {
|
|
||||||
record = globalSymbolRegistry[i];
|
|
||||||
if (record.symbol === symbol) return record.key;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* It affects array1 and appends array2 at the end of array1 */
|
|
||||||
var appendArray = function(array1, array2) {
|
|
||||||
// Returns immediately if these are not array or not array-like objects
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
typeof array1.length === "number" &&
|
|
||||||
array1.length >= 0 &&
|
|
||||||
typeof array2.length === "number" &&
|
|
||||||
array2.length >= 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
var length1 = Math.floor(array1.length),
|
|
||||||
length2 = Math.floor(array2.length),
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
array1.length = length1 + length2;
|
|
||||||
for (; i < length2; ++i)
|
|
||||||
if (array2.hasOwnProperty(i)) array1[length1 + i] = array2[i];
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6ObjectPrototypeToString = function toString() {
|
|
||||||
if (this === undefined || this === null) return objectToString.call(this);
|
|
||||||
// Add support for @@toStringTag symbol
|
|
||||||
if (typeof this[Symbol.toStringTag] === "string")
|
|
||||||
return "[object " + this[Symbol.toStringTag] + "]";
|
|
||||||
else return objectToString.call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6ArrayPrototypeConcat = function concat() {
|
|
||||||
if (this === undefined || this === null)
|
|
||||||
throw new TypeError("Array.prototype.concat called on null or undefined");
|
|
||||||
|
|
||||||
// Boxing 'this' value to wrapper object
|
|
||||||
var self = Object(this),
|
|
||||||
targets = slice.call(arguments),
|
|
||||||
outputs = []; // Later it may affected by Symbol
|
|
||||||
|
|
||||||
targets.unshift(self);
|
|
||||||
|
|
||||||
targets.forEach(function(target) {
|
|
||||||
// If target is primitive then just push
|
|
||||||
if (!isObject(target)) outputs.push(target);
|
|
||||||
// Here Symbol.isConcatSpreadable support is added
|
|
||||||
else if (typeof target[Symbol.isConcatSpreadable] !== "undefined") {
|
|
||||||
if (target[Symbol.isConcatSpreadable]) {
|
|
||||||
appendArray(outputs, target);
|
|
||||||
} else {
|
|
||||||
outputs.push(target);
|
|
||||||
}
|
|
||||||
} else if (isArray(target)) {
|
|
||||||
appendArray(outputs, target);
|
|
||||||
} else {
|
|
||||||
outputs.push(target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return outputs;
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6ForOfLoop = function(iterable, callback, thisArg) {
|
|
||||||
callback = typeof callback !== "function" ? emptyFunction : callback;
|
|
||||||
if (typeof iterable[Symbol.iterator] !== "function")
|
|
||||||
throw new TypeError("Iterable[Symbol.iterator] is not a function");
|
|
||||||
var iterator = iterable[Symbol.iterator](),
|
|
||||||
iterationResult;
|
|
||||||
if (typeof iterator.next !== "function")
|
|
||||||
throw new TypeError(".iterator.next is not a function");
|
|
||||||
while (true) {
|
|
||||||
iterationResult = iterator.next();
|
|
||||||
if (!isObject(iterationResult))
|
|
||||||
throw new TypeError(
|
|
||||||
"Iterator result " + iterationResult + " is not an object"
|
|
||||||
);
|
|
||||||
if (iterationResult.done) break;
|
|
||||||
callback.call(thisArg, iterationResult.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Provides simple inheritance functionality
|
|
||||||
var simpleInheritance = function(child, parent) {
|
|
||||||
if (typeof child !== "function" || typeof parent !== "function")
|
|
||||||
throw new TypeError("Child and Parent must be function type");
|
|
||||||
|
|
||||||
child.prototype = Object.create(parent.prototype);
|
|
||||||
child.prototype.constructor = child;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Behaves as Symbol function in ES6, take description and returns an unique object,
|
|
||||||
// but in ES6 this function returns 'symbol' primitive typed value.
|
|
||||||
// Its type is 'object' not 'symbol'.
|
|
||||||
// There is no wrapping in this case i.e. Object(sym) = sym.
|
|
||||||
var Symbol = function Symbol(desc) {
|
|
||||||
desc = typeof desc === "undefined" ? "" : String(desc);
|
|
||||||
|
|
||||||
if (this instanceof Symbol)
|
|
||||||
throw new TypeError("Symbol is not a constructor");
|
|
||||||
|
|
||||||
return setupSymbolInternals(Object.create(Symbol.prototype), desc);
|
|
||||||
};
|
|
||||||
|
|
||||||
defineProperties(Symbol, {
|
|
||||||
for: {
|
|
||||||
value: symbolFor,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
},
|
|
||||||
|
|
||||||
keyFor: {
|
|
||||||
value: symbolKeyFor,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
},
|
|
||||||
|
|
||||||
hasInstance: {
|
|
||||||
value: Symbol("Symbol.hasInstance")
|
|
||||||
},
|
|
||||||
|
|
||||||
isConcatSpreadable: {
|
|
||||||
value: Symbol("Symbol.isConcatSpreadable")
|
|
||||||
},
|
|
||||||
|
|
||||||
iterator: {
|
|
||||||
value: Symbol("Symbol.iterator")
|
|
||||||
},
|
|
||||||
|
|
||||||
toStringTag: {
|
|
||||||
value: Symbol("Symbol.toStringTag")
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// In ES6, this function returns like 'Symbol(<desc>)', but in this case
|
|
||||||
// this function returns the symbol's internal name to work properly.
|
|
||||||
Symbol.prototype.toString = function() {
|
|
||||||
return generateSymbolName(this._id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns itself but in ES6 It returns 'symbol' typed value.
|
|
||||||
Symbol.prototype.valueOf = function() {
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make Iterator like iterable
|
|
||||||
defineProperty(Iterator.prototype, Symbol.iterator.toString(), {
|
|
||||||
value: function() {
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
simpleInheritance(ArrayIterator, Iterator);
|
|
||||||
|
|
||||||
simpleInheritance(StringIterator, Iterator);
|
|
||||||
|
|
||||||
defineProperty(ArrayIterator.prototype, Symbol.toStringTag.toString(), {
|
|
||||||
value: "Array Iterator",
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(StringIterator.prototype, Symbol.toStringTag.toString(), {
|
|
||||||
value: "String Iterator",
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
// This iterator works on any Array or TypedArray or array-like objects
|
|
||||||
ArrayIterator.prototype.next = function next() {
|
|
||||||
if (!(this instanceof ArrayIterator))
|
|
||||||
throw new TypeError(
|
|
||||||
"Method Array Iterator.prototype.next called on incompatible receiver " +
|
|
||||||
String(this)
|
|
||||||
);
|
|
||||||
|
|
||||||
var self = this,
|
|
||||||
nextValue;
|
|
||||||
|
|
||||||
if (self._nextIndex === -1) {
|
|
||||||
return {
|
|
||||||
done: true,
|
|
||||||
value: undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(typeof self._array.length === "number" && self._array.length >= 0)) {
|
|
||||||
self._nextIndex = -1;
|
|
||||||
return {
|
|
||||||
done: true,
|
|
||||||
value: undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// _flag = 1 for [index, value]
|
|
||||||
// _flag = 2 for [value]
|
|
||||||
// _flag = 3 for [index]
|
|
||||||
if (self._nextIndex < Math.floor(self._array.length)) {
|
|
||||||
if (self._flag === 1)
|
|
||||||
nextValue = [self._nextIndex, self._array[self._nextIndex]];
|
|
||||||
else if (self._flag === 2) nextValue = self._array[self._nextIndex];
|
|
||||||
else if (self._flag === 3) nextValue = self._nextIndex;
|
|
||||||
self._nextIndex++;
|
|
||||||
return {
|
|
||||||
done: false,
|
|
||||||
value: nextValue
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
self._nextIndex = -1;
|
|
||||||
return {
|
|
||||||
done: true,
|
|
||||||
value: undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
StringIterator.prototype.next = function next() {
|
|
||||||
if (!(this instanceof StringIterator))
|
|
||||||
throw new TypeError(
|
|
||||||
"Method String Iterator.prototype.next called on incompatible receiver " +
|
|
||||||
String(this)
|
|
||||||
);
|
|
||||||
|
|
||||||
var self = this,
|
|
||||||
stringObject = new String(this._string),
|
|
||||||
nextValue;
|
|
||||||
|
|
||||||
if (self._nextIndex === -1) {
|
|
||||||
return {
|
|
||||||
done: true,
|
|
||||||
value: undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self._nextIndex < stringObject.length) {
|
|
||||||
nextValue = stringObject[self._nextIndex];
|
|
||||||
self._nextIndex++;
|
|
||||||
return {
|
|
||||||
done: false,
|
|
||||||
value: nextValue
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
self._nextIndex = -1;
|
|
||||||
return {
|
|
||||||
done: true,
|
|
||||||
value: undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6ArrayPrototypeIteratorSymbol = function values() {
|
|
||||||
if (this === undefined || this === null)
|
|
||||||
throw new TypeError("Cannot convert undefined or null to object");
|
|
||||||
|
|
||||||
var self = Object(this);
|
|
||||||
return new ArrayIterator(self, 2);
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6StringPrototypeIteratorSymbol = function values() {
|
|
||||||
if (this === undefined || this === null)
|
|
||||||
throw new TypeError(
|
|
||||||
"String.prototype[Symbol.iterator] called on null or undefined"
|
|
||||||
);
|
|
||||||
return new StringIterator(String(this), 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6ArrayPrototypeEntries = function entries() {
|
|
||||||
if (this === undefined || this === null)
|
|
||||||
throw new TypeError("Cannot convert undefined or null to object");
|
|
||||||
|
|
||||||
var self = Object(this);
|
|
||||||
return new ArrayIterator(self, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6ArrayPrototypeKeys = function keys() {
|
|
||||||
if (this === undefined || this === null)
|
|
||||||
throw new TypeError("Cannot convert undefined or null to object");
|
|
||||||
var self = Object(this);
|
|
||||||
return new ArrayIterator(self, 3);
|
|
||||||
};
|
|
||||||
|
|
||||||
var SpreadOperatorImpl = function(target, thisArg) {
|
|
||||||
this._target = target;
|
|
||||||
this._values = [];
|
|
||||||
this._thisArg = thisArg;
|
|
||||||
};
|
|
||||||
// All the arguments must be iterable
|
|
||||||
SpreadOperatorImpl.prototype.spread = function() {
|
|
||||||
var self = this;
|
|
||||||
slice.call(arguments).forEach(function(iterable) {
|
|
||||||
ES6.forOf(iterable, function(value) {
|
|
||||||
self._values.push(value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return self;
|
|
||||||
};
|
|
||||||
|
|
||||||
SpreadOperatorImpl.prototype.add = function() {
|
|
||||||
var self = this;
|
|
||||||
slice.call(arguments).forEach(function(value) {
|
|
||||||
self._values.push(value);
|
|
||||||
});
|
|
||||||
return self;
|
|
||||||
};
|
|
||||||
|
|
||||||
SpreadOperatorImpl.prototype.call = function(thisArg) {
|
|
||||||
if (typeof this._target !== "function")
|
|
||||||
throw new TypeError("Target is not a function");
|
|
||||||
thisArg = arguments.length <= 0 ? this._thisArg : thisArg;
|
|
||||||
return this._target.apply(thisArg, this._values);
|
|
||||||
};
|
|
||||||
|
|
||||||
SpreadOperatorImpl.prototype.new = function() {
|
|
||||||
if (typeof this._target !== "function")
|
|
||||||
throw new TypeError("Target is not a constructor");
|
|
||||||
|
|
||||||
var temp, returnValue;
|
|
||||||
temp = Object.create(this._target.prototype);
|
|
||||||
returnValue = this._target.apply(temp, this._values);
|
|
||||||
return isObject(returnValue) ? returnValue : temp;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Affects the target array
|
|
||||||
SpreadOperatorImpl.prototype.array = function() {
|
|
||||||
if (!isArray(this._target)) throw new TypeError("Target is not a array");
|
|
||||||
push.apply(this._target, this._values);
|
|
||||||
return this._target;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Target must be Array or function
|
|
||||||
var es6SpreadOperator = function spreadOperator(target, thisArg) {
|
|
||||||
if (!(typeof target === "function" || isArray(target)))
|
|
||||||
throw new TypeError(
|
|
||||||
"Spread operator only supports on array and function objects at this moment"
|
|
||||||
);
|
|
||||||
return new SpreadOperatorImpl(target, thisArg);
|
|
||||||
};
|
|
||||||
|
|
||||||
var es6ArrayFrom = function from(arrayLike, mapFn, thisArg) {
|
|
||||||
var constructor,
|
|
||||||
i = 0,
|
|
||||||
length,
|
|
||||||
outputs;
|
|
||||||
// Use the generic constructor
|
|
||||||
constructor = !isConstructor(this) ? Array : this;
|
|
||||||
if (arrayLike === undefined || arrayLike === null)
|
|
||||||
throw new TypeError("Cannot convert undefined or null to object");
|
|
||||||
|
|
||||||
arrayLike = Object(arrayLike);
|
|
||||||
if (mapFn === undefined) mapFn = simpleFunction;
|
|
||||||
else if (!isCallable(mapFn))
|
|
||||||
throw new TypeError(mapFn + " is not a function");
|
|
||||||
|
|
||||||
if (typeof arrayLike[Symbol.iterator] === "undefined") {
|
|
||||||
if (!(typeof arrayLike.length === "number" && arrayLike.length >= 0)) {
|
|
||||||
outputs = new constructor(0);
|
|
||||||
outputs.length = 0;
|
|
||||||
return outputs;
|
|
||||||
}
|
|
||||||
length = Math.floor(arrayLike.length);
|
|
||||||
outputs = new constructor(length);
|
|
||||||
outputs.length = length;
|
|
||||||
for (; i < length; ++i) outputs[i] = mapFn.call(thisArg, arrayLike[i]);
|
|
||||||
} else {
|
|
||||||
outputs = new constructor();
|
|
||||||
outputs.length = 0;
|
|
||||||
ES6.forOf(arrayLike, function(value) {
|
|
||||||
outputs.length++;
|
|
||||||
outputs[outputs.length - 1] = mapFn.call(thisArg, value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return outputs;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Export ES6 APIs and add all the patches to support Symbol in ES5
|
|
||||||
// If the running environment already supports ES6 then no patches will be applied,
|
|
||||||
if (isES6Running()) return ES6;
|
|
||||||
else {
|
|
||||||
// Some ES6 APIs can't be implemented in pure ES5, so this 'ES6' object provides
|
|
||||||
// some equivalent functionality of these features.
|
|
||||||
defineProperties(ES6, {
|
|
||||||
// Checks if a JS value is a symbol
|
|
||||||
// It can be used as equivalent api in ES6: typeof symbol === 'symbol'
|
|
||||||
isSymbol: {
|
|
||||||
value: isSymbol,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// Native ES5 'instanceof' operator does not support @@hasInstance symbol,
|
|
||||||
// this method provides same functionality of ES6 'instanceof' operator.
|
|
||||||
instanceOf: {
|
|
||||||
value: es6InstanceOfOperator,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// This method behaves exactly same as ES6 for...of loop.
|
|
||||||
forOf: {
|
|
||||||
value: es6ForOfLoop,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// This method gives same functionality of the spread operator of ES6
|
|
||||||
// It works on only functions and arrays.
|
|
||||||
// Limitation: You can't create array like this [...iterable, , , , 33] by this method,
|
|
||||||
// to achieve this you have to do like this [...iterable, undefined, undefined, undefined, 33]
|
|
||||||
spreadOperator: {
|
|
||||||
value: es6SpreadOperator,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(global, "Symbol", {
|
|
||||||
value: Symbol,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(Function.prototype, Symbol.hasInstance.toString(), {
|
|
||||||
value: es6FunctionPrototypeHasInstanceSymbol
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(Array.prototype, "concat", {
|
|
||||||
value: es6ArrayPrototypeConcat,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(Object.prototype, "toString", {
|
|
||||||
value: es6ObjectPrototypeToString,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(Array.prototype, Symbol.iterator.toString(), {
|
|
||||||
value: es6ArrayPrototypeIteratorSymbol,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(Array, "from", {
|
|
||||||
value: es6ArrayFrom,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(Array.prototype, "entries", {
|
|
||||||
value: es6ArrayPrototypeEntries,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(Array.prototype, "keys", {
|
|
||||||
value: es6ArrayPrototypeKeys,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProperty(String.prototype, Symbol.iterator.toString(), {
|
|
||||||
value: es6StringPrototypeIteratorSymbol,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return ES6;
|
|
||||||
});
|
|
||||||
/* eslint-enable */
|
|
||||||
|
|
||||||
// Polyfill Promise - used by popper.js
|
|
||||||
if (!window.Promise) {
|
|
||||||
window.Promise = true;
|
|
||||||
}
|
|
||||||
window.addEventListener(
|
|
||||||
"load",
|
|
||||||
function() {
|
|
||||||
window.Promise = require("rsvp").Promise;
|
|
||||||
},
|
|
||||||
false
|
|
||||||
);
|
|
|
@ -1,28 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require "rails_helper"
|
|
||||||
|
|
||||||
describe Middleware::AnonymousCache::Helper do
|
|
||||||
before { SiteSetting.discourse_unsupported_browser_enabled = true }
|
|
||||||
|
|
||||||
def env(opts = {})
|
|
||||||
{
|
|
||||||
"HTTP_HOST" => "http://test.com",
|
|
||||||
"REQUEST_URI" => "/path?bla=1",
|
|
||||||
"REQUEST_METHOD" => "GET",
|
|
||||||
"rack.input" => ""
|
|
||||||
}.merge(opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
def new_helper(opts = {})
|
|
||||||
Middleware::AnonymousCache::Helper.new(env(opts))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "includes ie in cache key" do
|
|
||||||
helper = new_helper
|
|
||||||
expect(helper.cache_key).to include("ie=false")
|
|
||||||
|
|
||||||
helper = new_helper("HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko")
|
|
||||||
expect(helper.cache_key).to include("ie=true")
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,37 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
describe 'Bootstrapping the Discourse App' do
|
|
||||||
let(:ie_agent) { "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko" }
|
|
||||||
|
|
||||||
context "when disabled" do
|
|
||||||
before do
|
|
||||||
SiteSetting.discourse_unsupported_browser_enabled = false
|
|
||||||
end
|
|
||||||
|
|
||||||
it "does not include the IE stylesheet or Javascript" do
|
|
||||||
get "/categories", headers: { "HTTP_USER_AGENT" => ie_agent }
|
|
||||||
expect(response.body).not_to match(/discourse-unsupported-browser-optional.js/)
|
|
||||||
expect(response.body).not_to match(/stylesheets\/discourse-unsupported-browser/)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when enabled" do
|
|
||||||
before do
|
|
||||||
SiteSetting.discourse_unsupported_browser_enabled = true
|
|
||||||
end
|
|
||||||
|
|
||||||
it "includes the IE js and css" do
|
|
||||||
get "/categories", headers: { "HTTP_USER_AGENT" => ie_agent }
|
|
||||||
expect(response.body).to match(/discourse-unsupported-browser-optional.js/)
|
|
||||||
expect(response.body).to match(/stylesheets\/discourse-unsupported-browser/)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "doesn't include IE stuff for non-IE browsers" do
|
|
||||||
get "/categories", headers: { "HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" }
|
|
||||||
expect(response.body).not_to match(/discourse-unsupported-browser-optional.js/)
|
|
||||||
expect(response.body).not_to match(/stylesheets\/discourse-unsupported-browser/)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -38,11 +38,6 @@ files:
|
||||||
- source_path: plugins/discourse-presence/config/locales/server.en.yml
|
- source_path: plugins/discourse-presence/config/locales/server.en.yml
|
||||||
destination_path: plugins/presence/server.yml
|
destination_path: plugins/presence/server.yml
|
||||||
|
|
||||||
- source_path: plugins/discourse-unsupported-browser/config/locales/client.en.yml
|
|
||||||
destination_path: plugins/unsupported-browser/client.yml
|
|
||||||
- source_path: plugins/discourse-unsupported-browser/config/locales/server.en.yml
|
|
||||||
destination_path: plugins/unsupported-browser/server.yml
|
|
||||||
|
|
||||||
- source_path: plugins/poll/config/locales/client.en.yml
|
- source_path: plugins/poll/config/locales/client.en.yml
|
||||||
destination_path: plugins/poll/client.yml
|
destination_path: plugins/poll/client.yml
|
||||||
- source_path: plugins/poll/config/locales/server.en.yml
|
- source_path: plugins/poll/config/locales/server.en.yml
|
||||||
|
|
Loading…
Reference in New Issue
Block a user